线程间的同步技术,主要以互斥锁和条件变量为主,条件变量和互斥所的配合使用可以很好的处理对于条件等待的线程间的同步问题。举个例子:当有两个变量x,y需要在多线程间同步并且学要根据他们之间的大小比较来启动不同的线程执行顺序,这便用到了条件变量这一技术。看代码
- #include <iostream>
- #include <pthread.h>
- using namespace std;
- pthread_cond_t qready = PTHREAD_COND_INITIALIZER; //初始构造条件变量
- pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER; //初始构造锁
- pthread_t tid1,tid2,tid3;
- int x = 10;
- int y = 20;
- void *thrd_1(void *arg)
- {
- pthread_mutex_lock(&qlock);
- while(x<y)
- {
- pthread_cond_wait(&qready,&qlock);
- }
- pthread_mutex_unlock(&qlock);
- cout<<"1"<<endl;
- sleep(5);
- }
- void *thrd_2(void *arg)
- {
- pthread_mutex_lock(&qlock);
- x = 20;
- y = 10;
- cout<<"has change x and y"<<endl;
- pthread_mutex_unlock(&qlock);
- if(x > y)
- {
- pthread_cond_signal(&qready);
- }
- cout<<"2"<<endl;
- }
- void *thrd_3(void *arg)
- {
- pthread_join(tid1,NULL);
- cout<<"3"<<endl;
- }
- int main(int argc,char **argv)
- {
- int err;
- err = pthread_create(&tid1,NULL,thrd_1,NULL);
- if(err != 0)
- {
- cout<<"pthread 1 create error"<<endl;
- }
- err = pthread_create(&tid2,NULL,thrd_2,NULL);
- if(err != 0)
- {
- cout<<"pthread 2 create error"<<endl;
- }
- err = pthread_create(&tid3,NULL,thrd_3,NULL);
- if(err != 0)
- {
- cout<<"pthread 3 create error"<<endl;
- }
- while(1)
- {
- sleep(1);
- }
- return 0;
-
- }
可以看到,创建了3个线程后,执行顺序2,1,3,即打印出的数字是213。为什么是这个顺序呢?我们接下去看,当创建tid1线程的时候,进入线程函数,并且加上了锁,然后进入pthread_cond_wait函数,这个函数的功能是等待qready这个条件变量成功,这个条件是什么呢?我们稍后在看,现在我们只要知道,这个函数在qready条件没满足的时候会卡在这里,并且,会把传入的互斥锁解锁,为什么要解锁的,拟可以想想,如果不解锁的话,那外部就没有可以对x,y的修改权,应为其他两个线程想要修改这两个值的话都需要对qclock进行枷锁。
好了线程1就这样,那之后就会运行线程2,我们看线程2的线程函数,该函数一开始也加了锁,但当线程1的pthread_cond_wait解锁之后,他就可以继续运行了,并且,在之后,它对x,y进行了修改,改好之后进行了解锁,并且调用了pthread_cond_signal通知线程1,现在可以知道了吧。这个满足的条件就是要x>y。
现在这里有个问题,一定要在发送通知之前解锁吗?答案是肯定的,为什么,因为如果先发送通知信号给线程1的时候,pthread_cond_wait可能在线程2的解锁之前就返回,而当它返回的时候,会再次将这个所进行锁定,而这个所还没有在线程2中解锁,应次会使其在次卡住。虽然这个卡住在线程2运行到解锁处会消除,但这并不符合我们有时的需求,所以最好还是在解锁之后在发送信号。
所以可以看出为什么线程2总是在线程1之前执行完毕,线程3就更不用说了,pthread_join你们懂的!!!
阅读(266) | 评论(0) | 转发(0) |