C++ 中的“同步”语句(类似 Java)






4.10/5 (22投票s)
2005年12月18日
2分钟阅读

141837
设计和实现一个类似于 Java 中 “synchronized” 语句的 C++ 语句。
引言
本文展示了如何在 C++ 中编写一个 `synchronized` 语句,使其工作方式类似于 Java。该代码的目标是使如下代码片段在 C++ 中可编译和执行:
synchronized(myMutex)
{
//TODO put synchronized code here
}
Mutex 类
以下代码片段展示了一个具有 lock/unlock 语义的 mutex 类(许多库中常见):
//mutex class class Mutex { public: //the default constructor Mutex() { InitializeCriticalSection(&m_criticalSection); } //destructor ~Mutex() { DeleteCriticalSection(&m_criticalSection); } //lock void lock() { EnterCriticalSection(&m_criticalSection); } //unlock void unlock() { LeaveCriticalSection(&m_criticalSection); } private: CRITICAL_SECTION m_criticalSection; };
上述类没有什么特别之处
- 它在构造时初始化临界区,
- 它删除临界区,
- `lock()` 方法锁定临界区,并且
- `unlock()` 方法解锁临界区。
我们将使用临界区,但任何同步原语都适用。
Lock 类
为了与 C++ 既定的代码实践保持一致,我们需要一个特殊的类来实现 RAII(资源获取即初始化)模式。以下代码片段展示了这样一个类:
//synchronization controller object class Lock { public: //the default constructor Lock(Mutex &mutex) : m_mutex(mutex), m_locked(true) { mutex.lock(); } //the destructor ~Lock() { m_mutex.unlock(); } //report the state of locking when used as a boolean operator bool () const { return m_locked; } //unlock void setUnlock() { m_locked = false; } private: Mutex &m_mutex; bool m_locked; };
需要注意的类中的事项:
- 它在构造时锁定互斥锁,并且
- 它在销毁时解锁互斥锁。
使用上述类非常简单:
Mutex mutex1;
...
Lock lock1(mutex1);
//synchronized code here
“synchronized” 宏
`synchronized` 语句可以编码为一个宏,如下所示:
#define synchronized(M) for(Lock M##_lock = M; M##_lock; M##_lock.setUnlock())
其中,参数 `M` 是用于锁定的互斥锁变量。
使用“synchronized”宏的示例
以下代码片段展示了如何使用 synchronized 宏:它协调两个线程,将字母表打印到标准输出。如果没有同步,输出将不正确:
//thread count int thread_count = 0; //mutex Mutex mutex1; //example thread DWORD CALLBACK thread_proc(LPVOID params) { for(int i = 0; i < 10; ++i) { synchronized(mutex1) { for(char c = 'A'; c <= 'Z'; ++c) { cout << c; } cout << endl; } } thread_count--; return 0; } //main int main() { thread_count = 2; CreateThread(0, 0, thread_proc, 0, 0, 0); CreateThread(0, 0, thread_proc, 0, 0, 0); while (thread_count) Sleep(0); getchar(); return 0; }
工作原理
该宏利用 C++ 的 `for` 语句的特性来执行以下操作(按所示顺序):
- 初始化部分:定义一个局部 lock 变量,该变量锁定给定的互斥锁;lock 变量包含一个内部标志,该标志设置为 true。
- 测试部分:测试 lock 变量,发现为 true:执行循环内的代码。
- 递增部分:将 lock 变量的内部标志设置为 false。
- 测试部分:测试 lock 变量,发现为 false:退出循环。
- 退出部分:销毁 lock 变量,解锁互斥锁。
相对于经典 RAII 的优势
以这种方式编写 RAII 具有一些相对于传统方法的优势:
- 它使代码更具可读性,
- 它有助于避免声明 lock 变量,并且
- 它将要同步的代码与同步范围绑定在一起。
注释
由于 `synchronized` 宏在销毁时会解锁其互斥锁,因此它是异常安全的。