Linux入门:线程同步与互斥(一)——互斥量

来源:互联网 发布:手机日记本软件 编辑:程序博客网 时间:2024/05/01 04:53

       多个线程同时访问共享数据时可能会冲突。比如,两个线程都要把某个全局变量加1,这个操作需要三个指令才能完成:

1.从内存读变量值到寄存器

2.寄存器的值加1

3.将寄存器的值写回内存

       由于给全局变量加1需要以上三步操作,而两个线程都要给它加1 的时候就可能在进行这三步操作的任意一步的时候被切出去,假设线程1 在给寄存器的值加1 之后刚想把寄存器的值的值写回内存的时候被切出去,此时它的上下文信息被保存;线程2开始操作这个全局变量,由于线程1还没有把加过之后的值写回内存,这时线程2 读到的仍然是全局变量的初始值,然后线程2就执行以上三步操作,完成之后又轮到线程1执行它自己的逻辑,此时它还原自己的上下文信息,将寄存器里的值写回内存,然而线程1和2各执行一次的操作值给全局变量加了1,没有达到我们预想的加2的效果。(什么情况下容易发生线程间切换:执行流由系统调用变为内核态,结束系统调用要切换回用户太的时候最容易触发线程间切换。用户态切换到内核态的三种方式:(1)系统调用,(2)异常,(3)外围设备的中断)

我们通过一个简单的程序来观察这一现象。

我们创建两个线程,各自把gCount的值累加5000次,正常情况下gCount的值应该等于10000:

#include <stdio.h>#include <pthread.h>//pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;int gCount = 0;void *thread_run(void *arg){int i = 0;int data = 0;while(i++ < 5000){//pthread_mutex_lock(&lock);data = gCount;printf("thread %lu count is:%d\n", data);gCount = data+1;//pthread_mutex_unlock(&lock);}}int main(){pthread_t id1, id2;pthread_create(&id1, NULL, thread_run, NULL);pthread_create(&id2, NULL, thread_run, NULL);pthread_join(id1, NULL);pthread_join(id2, NULL);//pthread_mutex_destroy(&lock);    printf("main thread count is:%d\n", gCount);return 0;}
然而结果每次都不相同:





        对于多线程的程序,多个执行流非原子的去访问临界资源,但没有对临界资源加以保护,访问冲突的问题是很普遍的,解决的办法是引入互斥锁,获得锁的线程可完成“读—修改—写”的操作,然后释放锁给其他线程,没有获得锁的线程只能等待而不能访问共享数据,这样“读—修改—写”三步操作组成一个原子操作,要么都执行,要么都不执行,就算在执行到其中一步的时候被切出去,也是抱着锁被切出去,其他线程没有访问这个共享数据的权利。

       互斥锁相当于二元信号量,只在线程中有效。

1.初始化互斥锁


2.加锁


3.解锁


4.销毁互斥锁


程序示例:



运行结果:




0 0
原创粉丝点击