条件变量,条件锁,互斥锁的简单理解
来源:互联网 发布:matlab从txt读取数据 编辑:程序博客网 时间:2024/05/15 23:45
看了一些网上有关条件锁的讲解,一般都讲得晦涩难懂,都是术语的感觉,看了让人似乎明白了一点,又有很多疑惑,所以我决定写下我自己的简单理解。在写条件锁之前,先讲讲互斥锁,请看例子:1,不使用互斥锁的情况:
#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>#include <string.h>pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;void printf_thread1(int n){ int i; //pthread_mutex_lock(&mylock); while(n--) { printf("this is thread111.and ##%d\n",n+1); for(i=0;i<1000000;i++){i++;i--;} } /pthread_mutex_unlock(&mylock);}void printf_thread2(int n){ int i; printf("hello xue,I like you very much!\n"); //pthread_mutex_lock(&mylock); while(n--) { printf("this is thread222.and ##%d\n",n+1); for(i=0;i<1000000;i++){i++;i--;} } //pthread_mutex_unlock(&mylock);}int main(){ pthread_t tid1,tid2; int err; void *tret; err=pthread_create(&tid1,NULL,printf_thread1,10);//创建线程 if(err!=0) { printf("pthread11_create error:%s\n",strerror(err)); exit(-1); } err=pthread_create(&tid2,NULL,printf_thread2,10); if(err!=0) { printf("pthread22_create error:%s\n",strerror(err)); exit(-1); } err=pthread_join(tid1,&tret);//阻塞等待线程id为tid1的线程,直到该线程退出 if(err!=0) { printf("can not join with thread11:%s\n",strerror(err)); exit(-1); } printf("thread 11 exit code %d\n",(int)tret); err=pthread_join(tid2,&tret); if(err!=0) { printf("can not join with thread22:%s\n",strerror(err)); exit(-1); } printf("thread 22 exit code %d\n",(int)tret); return 0;}
输出结果为:
可以看到线程1和线程2是交替执行的,而且每次的结果都有可能不同,造成原因是多线并发机制所致。
因此,我们把这个例子改成有锁的情况,改起来也很方便,就是把注释去掉就可以了:
#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>#include <string.h>pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;void printf_thread1(int n){ int i; pthread_mutex_lock(&mylock); while(n--) { printf("this is thread111.and ##%d\n",n+1); for(i=0;i<3000000;i++){i++;i--;} } pthread_mutex_unlock(&mylock);}void printf_thread2(int n){ int i; printf("hello xue,I like you very much!\n"); pthread_mutex_lock(&mylock); while(n--) { printf("this is thread222.and ##%d\n",n+1); for(i=0;i<3000000;i++){i++;i--;} } pthread_mutex_unlock(&mylock);}int main(){ pthread_t tid1,tid2; int err; void *tret; err=pthread_create(&tid1,NULL,printf_thread1,10);//创建线程 if(err!=0) { printf("pthread11_create error:%s\n",strerror(err)); exit(-1); } err=pthread_create(&tid2,NULL,printf_thread2,10); if(err!=0) { printf("pthread22_create error:%s\n",strerror(err)); exit(-1); } err=pthread_join(tid1,&tret);//阻塞等待线程id为tid1的线程,直到该线程退出 if(err!=0) { printf("can not join with thread11:%s\n",strerror(err)); exit(-1); } printf("thread 11 exit code %d\n",(int)tret); err=pthread_join(tid2,&tret); if(err!=0) { printf("can not join with thread22:%s\n",strerror(err)); exit(-1); } printf("thread 22 exit code %d\n",(int)tret); return 0;}
此时输出的结果为:
可以看到当从线程1跳到线程2的时候,只执行了加锁前的一句,直到线程1执行完,线程2才开始执行。现在体会到互斥锁的作用了吧!不客气呦。。。
下面再在这个例子上加入条件锁,来探究条件锁的用法,在贴代码前,我先说下我怎么用条件锁。我们做这样的改变,当线程1执行到n<6时,重新开始线程2执行,等到线程2执行完,又回到线程1,执行剩下部分。
代码如下:
#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>#include <string.h>pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;pthread_cond_t mycond;void printf_thread1(int n){ int i; pthread_mutex_lock(&mylock); while(n--) { printf("this is thread111.and ##%d\n",n+1); for(i=0;i<3000000;i++){i++;i--;} if(n==5) pthread_cond_wait(&mycond,&mylock); } pthread_mutex_unlock(&mylock);}void printf_thread2(int n){ int i; printf("hello xue,I like you very much!\n"); pthread_mutex_lock(&mylock); pthread_cond_signal(&mycond); while(n--) { printf("this is thread222.and ##%d\n",n+1); for(i=0;i<3000000;i++){i++;i--;} } pthread_mutex_unlock(&mylock);}int main(){ pthread_t tid1,tid2; int err; void *tret; err=pthread_create(&tid1,NULL,printf_thread1,10);//创建线程 if(err!=0) { printf("pthread11_create error:%s\n",strerror(err)); exit(-1); } err=pthread_create(&tid2,NULL,printf_thread2,10); if(err!=0) { printf("pthread22_create error:%s\n",strerror(err)); exit(-1); } err=pthread_join(tid1,&tret);//阻塞等待线程id为tid1的线程,直到该线程退出 if(err!=0) { printf("can not join with thread11:%s\n",strerror(err)); exit(-1); } printf("thread 11 exit code %d\n",(int)tret); err=pthread_join(tid2,&tret); if(err!=0) { printf("can not join with thread22:%s\n",strerror(err)); exit(-1); } printf("thread 22 exit code %d\n",(int)tret); return 0;}
输出结果为:
可以看到线程1执行到##6时就跳到了线程2执行,直到线程2执行完了再回来执行。
所以条件锁的作用相当于一个借锁的过程,pthread_cond_wait(&mycond,&mylock)这一语句,使得线程1获得的锁解开了,被移交到线程2(相当于借),此时线程1相当于挂起了,这里还涉及到了借的前提,就是必须要有锁,所以这一语句会有两个参数,一个是本身这个变量mycond,另一个是要借的锁mylock;而线程2中pthread_cond_signal(&mycond)这一语句有点像还锁,但有不是,因为不是立即还,而是要等线程2执行完了才还,所以这句话是赋予线程1继续拥有锁的权利,也就是把线程1重新放到等待队列中。
好了,现在你应该对互斥锁 下面这些概念有进一步的形象概念了吧:
阻塞在条件变量上pthread_cond_wait
解除在条件变量上的阻塞pthread_cond_signal
阻塞直到指定时间pthread_cond_timedwait
释放阻塞的所有线程pthread_cond_broadcast
释放条件变量pthread_cond_destroy
啦啦啦啦,总算写完了:
再贴一段别人对条件锁理解的形象比喻:
条件锁其实就是一个普通的锁加上了一个条件,如下面两行代码
//create a new lockprivate static Lock lock = new ReentrantLock();
//craete a conditionprivate static Condition newDeposit = lock.newCondition();
,重要的不是表象,是为什么需要这个条件锁,假设你有一个银行账户,密码你和你老婆都知道,你负责存钱,你老婆负责取钱,对存钱和取钱的代码都加了锁,所以是可以同步的。诶,平常存啊取的都挺好的,结果你俩矛盾了,你不去存钱,诶银行发现你老婆仍然可以取,而且透支了,你愿意不?银行愿意不?当然不愿意,也许你马上想到了,诶,我可以在取钱的时候加个条件去判断下,如果够取,那就让这个线程来取钱,否则呢?关键是这个否则呢?把这个线程干掉?不人道吧,让人家自己过N年后来取?这也不人道啊,评啥不是你通知人家老公存钱了,老婆过来看看,看够取不?诶,这个条件锁他就是这个为别人考虑的东西,你老婆一旦发现钱不够取了,他就打电话给你,嘿,小伙子,快点存钱,你说我有事,等会在存,等了很久,你存了一点,好,你在打电话给她,说,你可以去取取看,看过不,不够在打电话给我,够了直接取了就是。
饿死了,吃饭去
- 条件变量,条件锁,互斥锁的简单理解
- 条件变量的理解
- 理解 Linux 条件变量
- 理解 Linux 条件变量
- 理解 Linux 条件变量
- pthread_cond_wait理解以及互斥锁与条件变量使用的总结
- 对线程条件变量的理解
- 关于条件变量的一点理解
- 理解条件变量使用的一个例子
- 线程、互斥锁与条件变量实例理解
- 条件变量&互斥锁的使用
- 互斥锁 条件变量 读写锁
- 条件变量的用法
- 多线程的条件变量
- 多线程的条件变量
- 多线程的条件变量
- 条件变量的使用
- 条件变量的使用
- 关于const的底层实现
- android:shape的使用
- HDOJ 1097 A hard puzzle(循环节||快速幂)
- poj1458-Common Subsequence(最长公共子序列,LCS)
- Linux进程-命令行参数和环境列表
- 条件变量,条件锁,互斥锁的简单理解
- poj 1321 棋盘问题 简单dfs
- 如何给apk文件签名(一)
- mysql命令行常用命令
- 自定義佈局顯示dialog
- hdu 1272 小希的迷宫(并查集)
- 解决ECSHOP中transport.js和jquery的冲突问题
- 寻找距离某数最近的素数(C语言)
- cocos2dx 设置资源寻找路径