时间:2021-07-01 10:21:17 帮助过:10人阅读
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 如下图
结果:
加上锁之后,就输出10000
二、lock和unlock的实现原理
为了实现互斥锁操作,大多数体系结构都提供了swap或exchange指令,该指令的作用是把寄存器和内存单元的数据相交换,由于只有一条指令,保证了原子性,即使是多处理器平台,访问内存的总线周期也有先后,一个处理器上的交换指令执行时另一个处理器的交换指令只能等待总线周期。如下图的伪代码所示。unlock中的释放锁操作同样只用一条指令实现,以保证它的原子性。
三、死锁
・一般情况下,如果同一个线程先后两次调用lock,在第二次调用时,由于锁已经被占用,该线程会挂起等待别的线程释放锁,然而锁正是被自己占用着的,该线程又被挂起而没有机会释放锁,因此 就永远处于挂起等待状态了,这叫做死锁(Deadlock)。另一种典型的死锁情形是这样:线程A获得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放锁2,而这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和B都永远处于挂起状态了。
死锁形成的条件
①、互斥条件:一个资源每次只能被一个线程使用。
②、请求与保持条件:一个进程因请求资源而被阻塞时,对已获得的资源保持不放。
③、不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
④循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
如果涉及到更多的线程和更多的锁,则更容易引起死锁问题。写程序时应该尽量避免同时获得多个锁,如果一定有必要这么做,则有一个原则:如果所有线程在需要多个锁时都按相同的先后顺序(常见的是按Mutex变量的地址顺序)获得锁,则不会出现死锁。比如一个程序中用到锁1、锁2、锁3,它们所对应的Mutex变量的地址是锁1<锁2<锁3,那么 所有线程在需要同时获得2个或3个锁时都应该按锁1、锁2、锁3的顺序获得。如果要为所有的锁确定一个先后顺序比较困难,则应该尽量使用pthread_mutex_trylock调用代替pthread_mutex_lock调用,以免死锁。
以上就是Linux--线程的同步与互斥的内容,更多相关内容请关注PHP中文网(www.gxlcms.com)!