linux下条件变量使用笔记
本次笔记记录两个问题:
1,条件变量在使用时会有信号丢失现象;(使用g_nums记录信号,防止信号丢失)
2,条件变量的wait内部锁操作会在惊群现象的时候访问不可用资源,存在潜在的风险;(wait后再次对可用资源进行判断,防止操作不可用资源情况的发生)
在例子代码中都对上面两个现象实现对应的解决方案。
先列出第一种情况的例子
1 #include <iostream> 2 #include <pthread.h> 3 #include <unistd.h> 4 #include <stdio.h> 5 6 pthread_mutex_t mutex; 7 pthread_cond_t cond; 8 9 10 void* thread1( void* arg) 11 { 12 while(1) 13 { 14 15 pthread_mutex_lock(&mutex); 16 17 pthread_cond_wait(&cond, &mutex); 18 19 std::cout<<"the thread1 info: "<<std::endl; 20 21 pthread_mutex_unlock(&mutex); 22 sleep(1); 23 } 24 25 return null; 26 } 27 28 void* thread2(void* arg) 29 { 30 31 while(true){ 32 pthread_mutex_lock(&mutex); 33 34 pthread_cond_wait(&cond, &mutex); 35 36 std::cout<<"the thread2 info: "<<std::endl; 37 38 pthread_mutex_unlock(&mutex); 39 40 sleep(1); 41 } 42 43 return null; 44 } 45 46 47 int main( int argc, char*argv[] ) 48 { 49 pthread_t t1,t2; 50 51 pthread_mutex_init(&mutex, null); 52 53 pthread_cond_init(&cond, null); 54 55 pthread_create(&t1, null, thread1, null); 56 pthread_create(&t2, null, thread2, null); 57 58 //sleep(3); 59 60 for(size_t i=0; i<10; ++i) 61 { 62 //when send a signal to a cond, if no thread is waiting for this cond, so the signal will lost. 63 64 pthread_mutex_lock(&mutex); 65 pthread_cond_signal(&cond); 66 pthread_mutex_unlock(&mutex); 67 68 //sleep(1); 69 } 70 71 std::cout<<"please input the enter to quit.\n"; 72 getchar();//sleep(10); 73 74 return 0; 75 }
运行结果:
可见,发送了10次信号 ,条件变量却只触发了一次。该问题的解决方案会在后面给出的代码中写出,即使用g_nums来记录条件信号的个数。
下面来看看该笔记中的2)这种情况,惊群现象。。。
1 #include <iostream> 2 #include <pthread.h> 3 #include <unistd.h> 4 #include <stdio.h> 5 6 pthread_mutex_t mutex; 7 pthread_cond_t cond; 8 9 int g_nums=0;//如果没有这个计数,条件信号会有部分丢失,即在wait之前发的信号都会丢失 10 11 void* thread1( void* arg) 12 { 13 while(1) 14 { 15 16 pthread_mutex_lock(&mutex); 17 18 if(g_nums <=0 ) 19 pthread_cond_wait(&cond, &mutex); 20 21 //sleep(2); 22 if(g_nums <=0 ){//防止惊群现象,wait后再次lock但另一个线程已经用光了资源,如果不检查就使用会出问题 23 std::cout<<"the thread1 conflict..\n"; 24 continue; 25 } 26 27 --g_nums; 28 29 std::cout<<"the thread1 info: "<<std::endl; 30 31 pthread_mutex_unlock(&mutex); 32 sleep(1); 33 } 34 35 return null; 36 } 37 38 void* thread2(void* arg) 39 { 40 41 while(true){ 42 pthread_mutex_lock(&mutex); 43 44 if(g_nums <=0) 45 pthread_cond_wait(&cond, &mutex); 46 47 if(g_nums <= 0){//防止惊群现象,wait后再次lock但另一个线程已经用光了资源,如果不检查就使用会出问题 48 std::cout<<"thread2 conflict...\n"; 49 continue; 50 } 51 --g_nums; 52 53 std::cout<<"the thread2 info: "<<std::endl; 54 55 pthread_mutex_unlock(&mutex); 56 57 sleep(1); 58 } 59 60 return null; 61 } 62 63 64 int main( int argc, char*argv[] ) 65 { 66 pthread_t t1,t2; 67 68 pthread_mutex_init(&mutex, null); 69 70 pthread_cond_init(&cond, null); 71 72 pthread_create(&t1, null, thread1, null); 73 pthread_create(&t2, null, thread2, null); 74 75 //sleep(3); 76 77 for(size_t i=0; i<1; ++i) 78 { 79 //when send a signal to a cond, if no thread is waiting for this cond, so the signal will lost. 80 81 pthread_mutex_lock(&mutex); 82 ++g_nums; 83 pthread_cond_signal(&cond); 84 pthread_mutex_unlock(&mutex); 85 86 //sleep(1); 87 } 88 89 std::cout<<"please input the enter to quit.\n"; 90 getchar();//sleep(10); 91 92 return 0; 93 }
运行结果如下:
这种惊群现象不是必现的,但是有这个风险;所以在编程的时候需要注意这个坑。
造成这种情况的原因:
条件变量在与互斥量配合使用中,wait对互斥进行了如下操作,
1)lock——>2)如果没有可用资源则unlock,同时等待条件唤醒——>3)收到条件通知后——>4)lock——处理任务,dosomething...——>5)unlock
从上面的过程可以发现,3)是一个风险点,就像上面的例子一样,thread1和thread2同时收到通知,但thread2处理的快,thread1比较慢,此时thread2处理完任务并unlock,然后thread1才到4)lock,接下来如果thread1继续处理任务就是不对的了,如果是处理一个指针就可能造成系统崩溃;
本文为原创文章,如果转载请写明出处https://www.cnblogs.com/guoliushui/p/9510359.html
上一篇: 如何升级mac系统?苹果Mac免费升级系统方法介绍
下一篇: 工业4.0:从“产品”转向“服务”