【 Linux 】详解线程同步方法

一、什么是线程同步

        线程同步包含线程同步与线程互斥。

        线程同步:同步就是协同步调,按预定的先后顺序进行运行。线程同步是指多线程通过特定的设置(如:信号量、事件对象、临界区)来控制线程之间的执行顺序(即所谓的同步)也可以说是在线程之间通过同步建立起执行顺序的关系。

        线程互斥:线程互斥是指对于共享的进程系统资源,在各个单位线程访问时的排他性,当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其他使用该资源的线程必须等待,直到占用资源者释放该资源,线程互斥可以看成时一种特殊的线程同步。

二、线程同步的方式和机制

临界区、互斥对象:主要用于互斥控制,都具有拥有权的控制方法,只有拥有该对象的线程才能执行任务,所以拥有,执行完任务后一定要释放该对象。

信号量、事件对象:事件对象是以通知的方式进行控制的,主要用于同步控制。

1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问,在任意时刻只允许一个线程对共享资源访问,如果有多个线程试图访问公共资源,那么在一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后其他线程才可以抢占。

2、互斥对象:互斥对象和临界区很像,采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程同时访问,当前拥有拥有互斥对象的线程处理完任务后,必须将线程交出,以便其他线程访问。

     *总结互斥量Mutex:

             1>、互斥量是内核对象,它与关键段都有“线程所有权”,故不能用于线程同步;

             2>、互斥量能够用于多个进程之间的线程互斥问题

3、互斥锁对于多线程的程序的程序,访问冲突的问题是很普遍的,解决的办法是引入互斥锁,获得锁的线程可以完成“读----修改----写”的操作,然后释放锁给其他线程,没有获得锁的线程只能等待而不能访问共享数据,这样,“读----修改----写”的操作组成一个原子操作,要么都执行,要么都不执行,不会执行到中间被打断,也不会在其他处理器上并行作这个操作。

4、条件变量:线程间的同步还有这样一情况:线程A需要等待某个条件成立,才能继续往下执行,现在这个条件不成立了,线程A就阻塞等待,而线程B在执行过程中使这个条件成立的,就唤醒了线程A继续执行,在pthread库中通过条件变量来阻塞等待一个条件,或者唤醒等待这个条件的线程。

5、信号量:Mute变量是非0即1的,可看作一种资源的可用数量,初始化时Mutex是1,表示有一个可用资源,加锁时获得该资源,将Mutex减为0,表示不再有可用资源,解锁时,Mutex重新加到1,表示又有了一个可用资源,信号量和Mutex类似,表示可用资源的数量,和Mutex不同的是这个数量可以大于1。

三,四种线程同步控制方式

1,互斥对象

第一个CreateMutex
函数功能:创建互斥量(注意与事件Event的创建函数对比)
函数原型:

HANDLE  CreateMutex(LPSECURITY_ATTRIBUTES  lpMutexAttributes,BOOL  bInitialOwner, LPCTSTR  lpName);



    函数说明:第一个参数表示安全控制,一般直接传入NULL。第二个参数用来确定互斥量的初始拥有者。如果
传入TRUE表示互斥量对象内部会记录创建它的线程的线程ID号并将递归计数设置为1,由于该线程ID非零,所以互
斥量处于未触发状态。如果传入FALSE,那么互斥量对象内部的线程ID号将设置为NULL,递归计数设置为0,这意
味互斥量不为任何线程占用,处于触发状态。第三个参数用来设置互斥量的名称,在多个进程中的线程就是通过名
称来确保它们访问的是同一个互斥量。函数访问值:成功返回一个表示互斥量的句柄,失败返回NULL。

第二个打开互斥量

函数原型:

HANDLE  OpenMutex(DWORD   dwDesiredAccess,BOOL  bInheritHandle,LPCTSTR  lpName //名称);


    函数说明:第一个参数表示访问权限,对互斥量一般传入MUTEX_ALL_ACCESS。详细解释可以查看MSDN文档。
第二个参数表示互斥量句柄继承性,一般传入TRUE即可。第三个参数表示名称。某一个进程中的线程创建互斥量
后,其它进程中的线程就可以通过这个函数来找到这个互斥量。函数访问值:成功返回一个表示互斥量的句柄,失
败返回NULL。


第三个触发互斥量
函数原型:

BOOL  ReleaseMutex (HANDLE  hMutex);

    函数说明:访问互斥资源前应该要调用等待函数,结束访问时就要调用ReleaseMutex()来表示自己已经结束
访问,其它线程可以开始访问了。


最后一个清理互斥量
由于互斥量是内核对象,因此使用CloseHandle()就可以(这一点所有内核对象都一样)。

 

互斥对象的形象比喻:

       首先我们需要创建CreateMutex一把互斥对象,我们可以指明当前线程是否拥有它,互斥对象完全就像一把钥匙一样,我们用WaitForSignalObject来等待这把钥匙,但是这把钥匙被等到并且使用后必须释放-----ReleaseMutex ,不然别人永远无法等到。这样从等待到释放中间的代码段永远都是只有一个线程在执行,也就形成了互斥控制。当然互斥对象的句柄是要关闭的CloseHandle。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值