第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定

在C++里實(shí)現(xiàn) Java 的 synchronized 關(guān)鍵字

標(biāo)簽:
C#

  话说Java里有个很强大的关键字叫synchronized,可以方便的实现线程同步。今天异想天开,尝试在C++里模拟一个类似的。

  最近在学习C++的STL,看见智能指针这章节时,无不感叹利用语言的丰富特征,来各种实现各种巧妙的构思。最经典的莫过于使用栈对象构造/析构函数,来维护局部资源的初始化和释放。照着这个巧妙的方法,依样画葫芦自己也来写一个,来实现局部代码线程同步。

  Java里的synchronized有两种形式,一种是基于函数的,另种则是语块的。前者受C++的语法所限,估计是没法实现了,所以就尝试后者。
  块级语法很简单:

synchronized(syncObject) {    // code}

  
  因为Java所有变量都继承于Object,所以任意变量都能当作锁用。这在C++里无法简易实现,因此我们用特定的类型实例当作同步变量使用。
  先从最经典简易的同步类说起。

复制代码

struct Lock : CRITICAL_SECTION {
   Lock() {
       ::InitializeCriticalSection(this);
   }    ~Lock() {
       ::DeleteCriticalSection(this);
   }    void Enter() {
       ::EnterCriticalSection(this);
   }    void Leave() {
       ::LeaveCriticalSection(this);
   }
};

复制代码

 

  这是windows下实现线程同步最常见的封装。只需声明一个Lock实例,在需要同步的代码前后分别调用Enter和Leave即可。
  既然用起来这么简单,为什么还要继续改进?显然这种方法有个很大的缺陷,如果忘了调用Leave,或者在调用之前就return/throw退出,那么就会引起死锁。
  所以,我们需要类似auto_ptr的机制,自动维护栈数据的创建和删除。就暂且称它_auto_lock吧。

复制代码

struct _auto_lock {    Lock& _lock;    _auto_lock(Lock& lock) : _lock(lock) {        _lock.Enter();    }    ~_auto_lock() {        _lock.Leave();    }};

复制代码

  _auto_lock通过引用一个Lock实例来初始化,并立即锁住临界区;被销毁时则释放锁。

  有了这个机制,我们再也不用担心忘了调用.Leave()。只需提供一个Lock对象,就能在当前语块自动加锁解锁。再也不用担心死锁的问题了。

复制代码

Lock mylock; void Test(){    // code1 ...     // syn code    {        _auto_lock x(mylock);    }     // code2 ...}

复制代码


  进入syn code的"{"之后,_auto_lock被构造;无论用那种方式离开"}",析构函数都会被调用。
  上述代码类似的在stl和boost里都是及其常见的。利用栈对象的构造/析构函数维护局部资源,算是C++很常用的一技巧。
  我们的目标又近了一步。下面开始利用经典的宏定义,制造一颗synchronized语法糖,最终实现这样的语法:

复制代码

Lock mylock; void Test(){    // code1 ...     synchronized(mylock)    {        // sync code    }     // code2 ...}

复制代码

  显然需要一个叫synchronized宏,并且在里面定义_auto_lock。

#define synchronized(lock)        ..... _auto_lock x(lock) ......

  乍一看这语法很像循环,并且要在循环内定义变量,所以用for(;;)的结构是再好不过了。

for(_auto_lock x(mylock); ; )

  不过sync code我们只需执行一次,所以还需另一个变量来控制次数。由于for里面只能声明一种类型的变量,所以我们在外面再套一层循环:

for(int _i=0; _i<1; _i++)for(_auto_lock x(mylock); _i<1; _i++)

  synchronized宏将mylock替换成上述代码,既没有违反语法,也实现相同的流程。得益于循环语法,甚至可以在synchronized内使用break来跳出同步块

  
  我们将上述代码整理下,并做个简单的测试。


#include <stdio.h>
#include <windows.h>
#include <process.h>



struct Lock : CRITICAL_SECTION {
   Lock() {
       ::InitializeCriticalSection(this);
   }

   ~Lock() {
       ::DeleteCriticalSection(this);
   }

   void Enter() {
       ::EnterCriticalSection(this);
   }

   void Leave() {
       ::LeaveCriticalSection(this);
   }
};

struct _auto_lock {
   Lock& _lock;

   _auto_lock(Lock& lock) : _lock(lock) {
       _lock.Enter();
   }

   ~_auto_lock() {
       _lock.Leave();
   }
};

#define synchronized(lock)        for(int _i=0; _i<1; _i++)for(_auto_lock lock##_x(lock); _i<1; _i++)






// ---------- demo ----------
Lock mylock;


// ---------- test1 ----------
void WaitTest(int id)
{
   printf("No.%d waiting...\n", id);

   synchronized(mylock)
   {
       Sleep(1000);
   }

   printf("No.%d done\n", id);
}

void Test1()
{
   _beginthread((void(__cdecl*)(void*))WaitTest, 0, (void*) 1);
   _beginthread((void(__cdecl*)(void*))WaitTest, 0, (void*) 2);
   _beginthread((void(__cdecl*)(void*))WaitTest, 0, (void*) 3);
}





// ---------- test2 ----------
void ThrowFunc(int id)
{
   printf("No.%d waiting...\n", id);

   synchronized(mylock)
   {
       Sleep(1000);
       throw "some err";
   }

   printf("No.%d done\n", id);
}

void ThrowTest(int id)
{
   try
   {
       ThrowFunc(id);
   }
   catch(...)
   {
       printf("%d excepted\n", id);
   }
}

void Test2()
{
   _beginthread((void(__cdecl*)(void*))ThrowTest, 0, (void*) 1);
   _beginthread((void(__cdecl*)(void*))ThrowTest, 0, (void*) 2);
   _beginthread((void(__cdecl*)(void*))ThrowTest, 0, (void*) 3);
}



// ---------- test3 ----------
void BreakTest(int id)
{
   printf("No.%d waiting...\n", id);

   synchronized(mylock)
   {
       Sleep(1000);
       break;
       Sleep(99999999);
   }

   printf("No.%d done\n", id);
}

void Test3()
{
   _beginthread((void(__cdecl*)(void*))BreakTest, 0, (void*) 1);
   _beginthread((void(__cdecl*)(void*))BreakTest, 0, (void*) 2);
   _beginthread((void(__cdecl*)(void*))BreakTest, 0, (void*) 3);
}




int main(int argc, char* argv[])
{
   printf("Wait Test. Press any key to start...\n");
   getchar();
   Test1();

   getchar();
   printf("Exception Test. Press any key to start...\n");
   getchar();
   Test2();

   getchar();
   printf("Break Test. Press any key to start...\n");
   getchar();
   Test3();

   getchar();
   return 0;
}


  使用语法糖除了好看外,有个最重要的功能就是可以在synchronized同步块里使用break来跳出,并且不会引起死锁,这是其他方法无法实现的。

點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺(jué)得本文不錯(cuò),就分享一下吧!

評(píng)論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評(píng)論
  • 收藏
  • 共同學(xué)習(xí),寫(xiě)下你的評(píng)論
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說(shuō)多少就多少
贊賞金額會(huì)直接到老師賬戶(hù)
支付方式
打開(kāi)微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊(cè)有機(jī)會(huì)得

100積分直接送

付費(fèi)專(zhuān)欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會(huì)
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

舉報(bào)

0/150
提交
取消