尝试在C++里实现 Java 的 synchronized 关键字
来源:互联网 发布:linux 驱动 usleep 编辑:程序博客网 时间:2024/06/07 04:00
尝试在C++里实现 Java 的 synchronized 关键字
话说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;}
- 尝试在C++里实现 Java 的 synchronized 关键字
- 尝试在C++里实现 Java 的 synchronized 关键字
- 尝试在C++里实现 Java 的 synchronized 关键字
- java同步关键字Synchronized 的实现原理
- java中synchronized关键字的实现
- java的synchronized关键字
- Java的关键字synchronized
- java的synchronized关键字
- java里同步关键字synchronized 理解
- c++实现java synchronized关键字
- Java关于Synchronized关键字在不同位置使用的理解
- Java关于Synchronized关键字在不同位置使用的理解
- JAVA的关键字:final && synchronized
- 关于java的synchronized 关键字
- synchronized 关键字的java应用
- java synchronized关键字的详解
- Java synchronized关键字的认识
- Java Synchronized关键字的使用
- C语言实现的线程池
- HDFS特点(优缺点)
- spring定时器触发时间表达式规则
- 混合拉普拉斯
- LDA主题模型代码实现流程
- 尝试在C++里实现 Java 的 synchronized 关键字
- webpack代码分割-使用require.ensure
- Uncaught TypeError: Cannot read property 'getItem' of null
- Picasso的简单使用
- 腾讯arttemplate模板官方介绍
- 导入项目工程后如果出现下面的错误该如何解决
- 快速排序
- iOS 给字符串添加删除线,下划线效果遇到的坑(10.3 与 8.1 系统)
- Pl/sql 中文乱码出现????