线程: 4种同步(浅析)

  ps: 本文只为记述某在工作学习中的所得,便于以后重新学习。如有错误,欢迎指正!

  同步:协同步调,按照某种顺序先后执行,防止数据混乱

  由于线程是按时间片轮循的,所以当多个线程访问同一个数据(全局)对其进行修改时,会造成数据混乱。例如,线程A和线程B都要访问数据Data时,当A先访问对其进行修改,此时A的时间片用完,到B访问Data,再次对Data进行修改。此后在由A访问Data时,此时Data的值为B所修改的值。为了避免类似问题,可以用同步处理。

四种同步:

  1.互斥

  某一时刻只允许一个线程能够访问共享资源。只有当该线程执行完,其他线程才能开始执行。

 

代码:

 

  

 

     

 

  

运行结果:

 

  

 

不使用互斥结果对比:

 

   

 

 

  2.信号灯

  指定数量的线程按时间片轮循开始执行。比方说,有100个线程,现在只允许5个可以执行。那么这100个线程抢占资源,最先获取权限的5个线程开始执行,只有当这5个线程中的某一个运行结束,才能执行其他线程。即每有一个线程获取信号,信号灯计数-1,每执行完一个线程信号灯计数+1.计数为0时,表示饱和,无法容纳更多线程。

  

代码:

 

   

 

    

 

结果:3个线程抢占2个公共资源 先抢到的2个线程并行运行 某一个退出 第三个开始执行 

 

   ps:线程运行完记得释放,否则后续线程可能获取不到信号。

 

   

 

 

 

  3.事件

  指定某一线程执行完,才能开始执行其他指定线程。比方说,线程A执行完,才能执行线程B,线程B执行完,才能执行线程C...是一个顺序的过程。

代码:

 

    

 

   

 

   

 

结果:

 

    

 

  4.临界区

  跟互斥类似,只有线程进入临界区,访问共享资源时,才可以被执行,其他线程要等该线程执行完,才能开始执行。

 

代码:

 

   

 

    

 

    

结果:

 

   

=======================================================================================================================================

 总结:

  互斥: 通过CreateMutex函数来创建互斥锁,ReleaseMutex函数释放。

  信号灯:通过CreateSemaphore函数创建信号灯,ReleaseSemaphore函数释放

  事件: 通过CreateEvent函数创建事件,SetEvent或者PulSeEvent函数将事件设置为有信号,ResetEvent设置为无信号

  互斥、信号灯、事件均通过WaitForSingleObject或WaitForMultipleObjects函数等待信号量响应

  临界区:对象为结构体CRITICAL_SECTION,通过InitializeCriticalSection函数对该结构体对象进行初始化,EnterCriticalSection函数进入临界区,LeaveCriticalSection函数离开临界区。当不在需要该临界区时使用DeleteCriticalSection函数将其删除,释放系统资源(本文未处理)。

  ps:互斥、信号灯、事件都是内核对象,可以跨进程使用,而临界区不是内核对象,只能在当前进程中使用。互斥临界区两者作用基本上完全一样,在当前进程中使用时,临界区的效率明显高于互斥。一般来讲,跨进程使用互斥,不需要跨进程使用临界区。

   

 

 

  

posted @ 2019-01-02 18:06  十七律丶  阅读(142)  评论(0)    收藏  举报