此篇讨论一下c++中的线程同步。
线程同步方式:
临界区
事件
互斥量
信号量
为什么要线程同步?
从之前的讨论及实际的项目中,可以看到线程同步给我们带来了很多便利性,但是多线程也同时给我们带来了很多麻烦:一方面,在开发调试阶段带来了很大的难度;另一方面,则需要考虑资源访问的一致性原则。因为在程序中使用多线程的时候,每一个线程并不会各行各事,每个线程之间必然会存在一些联系。如果两个或者多个线程访问同一个独占性的系统资源,这样会导致系统错误。
下面对实现线程同步的几种方法分别介绍
(1) 临界区
临界区是一段独占对某些共享资源的访问代码,在任意时刻只允许一个线程对共享资源访问。如果有多个线程试图同时访问临界区,那么只有一个线程进入临界区,其他试图访问临界区的线程将被挂起,并一直持续到进入临界区的线程离开,其他线程可以继续抢占临界区。
需要说明的是,在使用临界区时,一般不允许其运行时间过长,因为只要进入临界区的线程不离开,其他视图进入此临界区的线程都会挂起,进入等待状态,因此这样在一定程度上影响程序的性能。因此,不要使临界区一直处于未释放的状态。
还需要注意的是,虽然临界区同步速度比较快,但是只能用来同步本进程内的线程,而不能跨线程同步。
MFC中,有一个CCriticalSection类,此类中有两个方法Lock和UnLock,只需要在需要同步的代码前后假如这两个函数,就可以实现临界区资源。
例子如下(部分代码):
- CCriticalSection critical_section;
- char g_array[10];
- UINT WriteW(LPVOID pParam)
- {
- CEdit *pEdit = (CEdit *)pParam;
- pEdit->SetWindowText(" ");
- <span style="color:#ff0000;">critical_section.Lock()</span>;//锁定临界区
- for (int i=0; i<10; i++)
- {
- g_array[i]='W';
- pEdit->SetWindowText(g_array);
- Sleep(1000);
- }
- <span style="color:#ff0000;">critical_section.Unlock();</span>
- return 0;
- }
- UINT WriteD(LPVOID pParam)
- {
- CEdit *pEdit = (CEdit *)pParam;
- pEdit->SetWindowText(" ");
- <span style="color:#ff0000;">critical_section.Lock();</span>
- for (int i=0; i<10; i++)
- {
- g_array[i]='D';
- pEdit->SetWindowText(g_array);
- Sleep(1000);
- }
- <span style="color:#ff0000;">critical_section.Unlock();</span>
- return 0;
- }
创建线程:
- void CMthread8Dlg::OnWritew()
- {
- // TODO: Add your control notification handler code here
- CWinThread *pWriteW = AfxBeginThread((AFX_THREADPROC)WriteW,
- &m_ctrW,
- THREAD_PRIORITY_NORMAL,
- 0,
- CREATE_SUSPENDED);