Linux--线程的同步与互斥

1、 mutex互斥量多线程

   同步:就是对资源的访问有序。互斥:就是任一时刻来讲只有一个在执行;可是对于多线程的程序来讲,访问冲突的问题是很广泛的,解决的办法是引入互斥锁(Mutex,MutualExclusive Lock),得到锁的线程能够完成“读-修改-写”的操做,而后释放锁给其它线程,没有得到锁的线程只能等待而不能访问共享数据,这样“读-修改-写”三步操做组成一个原子操做,要么都执行,要么都不执行,不会执行到中间被打断,也不会在其它处理器上并行作这个操做。ide

   互斥锁用pthread_mutex_t类型的变量表示。用pthread_mutex_init初始化,用hread_destory()销毁。成功返回0,失败返回错误号。。若是Mutex变量是静态分配的(全局变量 或static变量),也能够用宏定义PTHREAD_MUTEX_INITIALIZER来初始化,至关于用pthread_mutex_init初始化而且attr参数为NULL函数

   一个线程能够调用pthread_mutex_lock得到Mutex,若是这时另外一个线程已经调pthread_mutex_lock得到了该Mutex,则当前线程须要挂起等待,直到另外一个线程调用pthread_mutex_unlock释放Mutex,当前线程被唤醒,才能得到该Mutex并继续执行。意思就是说若是有一个线程对mutex上了锁,没有开锁,另一个线程想得到mutex,就得挂机等待,直到上锁的线程开了锁释放开mutex以后,该线程被唤醒,才能得到mutex.spa

   若是一个线程既想得到锁,又不想挂起等待,能够调用pthread_mutex_trylock,若是Mutex已经被另外一个线程得到,这个函数会失败返回EBUSY,而不会使线程挂起等待。线程

    

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 static int g_count=0;
  5 void * addWrite(void * arg)
  6 {
  7     int count=0;
  8     int value=0;
  9     while(count++ <5000)
 10     {
 11         value=g_count;
 12         printf("g_count is %d\n",g_count);
 13         g_count=value+1;
 14     }
 15 }
 16 int main()
 17 {
 18     pthread_t id1;
 19     pthread_t id2;
 20     int ret=pthread_create(&id1,NULL,addWrite,NULL);
 21     int res=pthread_create(&id2,NULL,addWrite,NULL);
 22     pthread_join(id1,NULL);
 23     pthread_join(id2,NULL);

    

咱们建立两个线程,各自把g_count增长5000次,正常状况下最后counter应该等于10000,但事实上每次运行该程序的结果都不同,有时候数到5000多,有时候数到6000多可是加上锁以后(在)第五行加上pthread_mutex_init 以下图blog

wKioL1cTTIPj_vooAAGGy0TV8xs368.jpg

结果:进程

wKioL1cTTOOS1iaZAAGPtBKpZNA377.jpg

加上锁以后,就输出10000内存

2、lock和unlock的实现原理
资源

    为了实现互斥锁操做,大多数体系结构都提供了swap或exchange指令,该指令的做用是把寄存器和内存单元的数据相交换,因为只有一条指令,保证了原子性,即便是多处理器平台,访问内存的总线周期也有前后,一个处理器上的交换指令执行时另外一个处理器的交换指令只能等待总线周期。以下图的伪代码所示。unlock中的释放锁操做一样只用一条指令实现,以保证它的原子性。get

wKioL1cTUnbgI4-UAACscmPnqN4295.jpg

3、死锁

·通常状况下,若是同一个线程前后两次调用lock,在第二次调用时,因为锁已经被占用,该线程会挂起等待别的线程释放锁,然而锁正是被本身占用着的,该线程又被挂起而没有机会释放锁,所以 就永远处于挂起等待状态了,这叫作死锁(Deadlock)。另外一种典型的死锁情形是这样:线程A得到了锁1,线程B得到了锁2,这时线程A调用lock试图得到锁2,结果是须要挂起等待线程B释放锁2,而这时线程B也调用lock试图得到锁1,结果是须要挂起等待线程A释放锁1,因而线程A和B都永远处于挂起状态了。

死锁造成的条件

    ①、互斥条件:一个资源每次只能被一个线程使用。

    ②、请求与保持条件:一个进程因请求资源而被阻塞时,对已得到的资源保持不放。

    ③、不剥夺条件:进程已得到的资源,在未使用完以前,不能强行剥夺。

    ④循环等待条件:若干进程之间造成一种头尾相接的循环等待资源关系

  若是涉及到更多的线程和更多的锁,则更容易引发死锁问题。写程序时应该尽可能避免同时得到多个锁,若是必定有必要这么作,则有一个原则:若是全部线程在须要多个锁时都按相同的前后顺序(常见的是按Mutex变量的地址顺序)得到锁,则不会出现死锁。好比一个程序中用到锁一、锁二、锁3,它们所对应的Mutex变量的地址是锁1<锁2<锁3,那么 全部线程在须要同时得到2个或3个锁时都应该按锁一、锁二、锁3的顺序得到。若是要为全部的锁肯定一个前后顺序比较困难,则应该尽可能使用pthread_mutex_trylock调用代替pthread_mutex_lock调用,以避免死锁。

相关文章
相关标签/搜索