天天看点

面试归来4--多线程同步机制区别

佛说,彼岸花,开一千年,落一千年,花叶永不相见。情不为因果,缘注定生死。

1 进程的组成:虚拟的地址空间,代码,系统资源。

  线程分类:用户界面线程,主线程。举例:CWinApp 就是一个用户界面线程。

  线程间通信的方式有两种:1 全局变量 2 自定义消息响应

  线程间同步的方式有四种:MFC提供的同步对象

                          1 临界区 CCriticalSection

                          2 事件 CEvent

                          3 互斥量 CMutex

                          4 信号量 CSemaphore

1 使用场合:当多个线程 访问一个独占性的共享资源

  使用方法:(1)定义CCriticalSection 的一个全局对象。 CCriticalSection  ;

            (2)在需要保护的代码或资源前调用。

            critical_section.Lock();

            线程调用这个函数Lock()获得临界区对象。如果其他线程没有占有这个临界区对象,调用Lock()的线程获得临界区对象;否则

            调用Lock()的线程就被挂起,放入一个由系统维护的队列,直到占有临界区的线程结束为止。

            (3)访问临界区完闭,

             critical_section.Unlock();

             再通俗一点讲,就是线程A执行到critical_section.Lock();语句时,如果其它线程(B)正在执行critical_section.Lock();语句             后且critical_section. Unlock();语句前的语句时,线程A就会等待,直到线程B执行完critical_section. Unlock();语句                 ,线程A才会继续执行。

2 使用场合:CEvent 支持事件。当事件是一个线程在某种情况下用来唤醒另外一个线程的同步对象。

  状态:有信号和无信号

  分类:自动事件和人工事件。自动和人工的区别是:CEvent 的无信号状态是由系统自动重置的还是有开发者调用函数实现的。

  1、CEvent(BOOL bInitiallyOwn=FALSE,

          BOOL bManualReset=FALSE,

          LPCTSTR lpszName=NULL,

          LPSECURITY_ATTRIBUTES lpsaAttribute=NULL);

   bInitiallyOwn:指定事件对象初始化状态,TRUE为有信号,FALSE为无信号;

bManualReset:指定要创建的事件是属于人工事件还是自动事件。TRUE为人工事件,FALSE为自动事件;

后两个参数一般设为NULL,在此不作过多说明。

2、BOOL CEvent::SetEvent();

  将 CEvent 类对象的状态设置为有信号状态。如果事件是人工事件,则 CEvent 类对象保持为有信号状态,直到调用成员函数ResetEvent()将 其重新设为无信号状态时为止。如果CEvent 类对象为自动事件,则在SetEvent()将事件设置为有信号状态后,CEvent 类对象由系统自动重置为无信号状态。

如果该函数执行成功,则返回非零值,否则返回零。 3、BOOL CEvent::ResetEvent();

  该函数将事件的状态设置为无信号状态,并保持该状态直至SetEvent()被调用时为止。由于自动事件是由系统自动重置,故自动事件不需

要调用该函数。如果该函数执行成功,返回非零值,否则返回零。

使用方法:线程(A),线程(B) 如果想先执行线程(A)在执行线程(B),那么在线程(A)中代码的最后调用 CEvent对象的SetEvent(),将事件对象置为有信号状态,在线程(B)代码的开始调用WaitForSingleObject() 那么WaitForSingleObject()函数就可以一直监视CEvent对象一旦此对象为有信号状态那么线程(B)就可以执行了,从而实现了现场同步。

3 互斥对象和临界区很像。CMutex

  区别:CMutex既可以在进程间使用,也可以在同一进程的各个线程间使用。

4 CSemaphore

  使用场合:允许多个线程同时访问一个共享资源,同时规定了同时访问这个共享资源的线程数目。

            其内部有一个计数器当有线程访问这个共享资源时 计数器自动减1 当计数器为0时就不运行其他线程在访问共享资源。

           (1)建立一个信号量对象

              CSemaphore semaphore(2,2);

              定义一个CSingleLock,CMutiLock;

              CSingleLock  singlelock(semaphore);

             要减小这个信号Semaphore的计数值,只须调用CSingleLock对象的成员函数Lock()即可:

             SingleLock.Lock();

          同样,通过调用UnLock()来释放这个信号量,即:SingleLock.UnLock();

        示例代码:http://www.vckbase.com/document/viewdoc/?id=762

继续阅读