当前位置: 首页 > news >正文

Linux 线程管理

 

解析1

LINUX环境下多线程编程肯定会遇到需要条件变量的情况,此时必然要使用pthread_cond_wait()函数。但这个函数的执行过程比较难于理解。
    pthread_cond_wait()的工作流程如下(以MAN中的EXAMPLE为例):
       Consider two shared variables x and y, protected by the mutex mut, and a condition vari-
       able cond that is to be signaled whenever x becomes greater than y.

              int x,y;
              pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
              pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

       Waiting until x is greater than y is performed as follows:

              pthread_mutex_lock(&mut);
              while (x <= y) {
                      pthread_cond_wait(&cond, &mut);
              }
             
              pthread_mutex_unlock(&mut);

       Modifications on x and y that may cause x to become greater than y should signal the con-
       dition if needed:

              pthread_mutex_lock(&mut);
             
              if (x > y) pthread_cond_broadcast(&cond);
              pthread_mutex_unlock(&mut);

     这个例子的意思是,两个线程要修改X和 Y的值,第一个线程当X<=Y时就挂起,直到X>Y时才继续执行(由第二个线程可能会修改X,Y的值,当X>Y时唤醒第一个线程),即 首先初始化一个普通互斥量mut和一个条件变量cond。之后分别在两个线程中分别执行如下函数体:

              pthread_mutex_lock(&mut);
              while (x <= y) {
                      pthread_cond_wait(&cond, &mut);
              }
             
              pthread_mutex_unlock(&mut);
     while作用:因为可能有多个线程等待,所以 pthread_cond_wait 返回时,假如A线程会先获取mut,此时其他线程变阻塞,如果A修改了x,y使x<=y则其他线程就没必要再执行了,所以要加while判断。

和:       pthread_mutex_lock(&mut);
             
              if (x > y) pthread_cond_signal(&cond);
              pthread_mutex_unlock(&mut); 
    其实函数的执行过程非常简单,在第一个线程执行到pthread_cond_wait(&cond,&mut)时,此时如果X<=Y,则此函数就将mut互斥量解锁 ,再将cond条件变量加锁 ,此时第一个线程挂起 (不占用任何CPU周期)。
    而在第二个线程中,本来因为mut被第一个线程锁住而阻塞,此时因为mut已经释放,所以可以获得锁mut,并且进行修改X和Y的值,在修改之后,一个IF语句判定是不是X>Y,如果是,则此时pthread_cond_signal()函数会唤醒第一个线程 ,并在下一句中释放互斥量mut。然后第一个线程开始从pthread_cond_wait()执行,首先要再次锁mut , 如果锁成功,再进行条件的判断 (至于为什么用WHILE,即在被唤醒之后还要再判断,后面有原因分析),如果满足条件,则被唤醒 进行处理,最后释放互斥量mut 。

    至于为什么在被唤醒之后还要再次进行条件判断(即为什么要使用while循环来判断条件),是因为可能有“惊群效应”。有人觉得此处既然是被唤醒的,肯定 是满足条件了,其实不然。如果是多个线程都在等待这个条件,而同时只能有一个线程进行处理,此时就必须要再次条件判断,以使只有一个线程进入临界区处理。 对此,转来一段:

引用下POSIX的RATIONALE: 

Condition Wait Semantics 

It is important to note that when pthread_cond_wait() and pthread_cond_timedwait() return without error, the associated predicate may still be false. Similarly, when pthread_cond_timedwait() returns with the timeout error, the associated predicate may be true due to an unavoidable race between the expiration of the timeout and the predicate state change. 

The application needs to recheck the predicate on any return because it cannot be sure there is another thread waiting on the thread to handle the signal, and if there is not then the signal is lost. The burden is on the application to check the predicate. 

Some implementations, particularly on a multi-processor, may sometimes cause multiple threads to wake up when the condition variable is signaled simultaneously on different processors. 

In general, whenever a condition wait returns, the thread has to re-evaluate the predicate associated with the condition wait to determine whether it can safely proceed, should wait again, or should declare a timeout. A return from the wait does not imply that the associated predicate is either true or false. 

It is thus recommended that a condition wait be enclosed in the equivalent of a "while loop" that checks the predicate. 

从上文可以看出: 
1,pthread_cond_signal在多处理器上可能同时唤醒多个线程,当你只能让一个线程处理某个任务时,其它被唤醒的线程就需要继续 wait,while循环的意义就体现在这里了,而且规范要求pthread_cond_signal至少唤醒一个pthread_cond_wait上 的线程,其实有些实现为了简单在单处理器上也会唤醒多个线程. 
2,某些应用,如线程池,pthread_cond_broadcast唤醒全部线程,但我们通常只需要一部分线程去做执行任务,所以其它的线程需要继续wait.所以强烈推荐此处使用while循环.

       其实说白了很简单,就是pthread_cond_signal()也可能唤醒多个线程,而如果你同时只允许一个线程访问的话,就必须要使用while来进行条件判断,以保证临界区内只有一个线程在处理。

 

解析2

2.使用条件变量的线程同步(推荐)

采用阻塞和消息方式可以极大程度上减少资源的浪费以及增加实时性

线程条件变量pthread_cond_t

线程等待某个条件

int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex); 

通知函数

通知所有的线程

int pthread_cond_broadcast(pthread_cond_t *cond); 

只通知一个线程

int pthread_cond_signal(pthread_cond_t *cond); 

---------------------------------------------------------------------------------

正确的使用方法


 pthread_cond_wait用法:

pthread_mutex_lock(&mutex);

while(condition_is_false)

{

 pthread_cond_wait(&cond,&mutex);

 }

condition_is_false=true;  //此操作是带锁的,也就是说只有一个线程同时进入这块

pthread_mutex_unlock(&mutex);

 ----------------------------------------------------


pthread_cond_signal用法: 

pthread_mutex_lock(&mutex);

condition_is_false=false;

pthread_cond_signal(&cond)

pthread_mutex_unlock(&mutex)

--------------------------------------------------------

 记住上面这种用法!!!可以避免误用pthread_cond_broadcast而释放了所有条件变量

参考 http://blog.csdn.net/mashang123456789/article/details/9792677

 

相关文章:

  • tomcat 热布署
  • chrome扩展demo1-小时钟
  • java.io.Serializable引发的问题
  • oc之类排序
  • oKit项目管理软件正式提供在线服务
  • Red Hat 安装
  • 查看LoadRunner脚本请求日志和服务器返回值方法
  • iOS开发笔记 2、Cocoa简明
  • 烟花散尽漫说无(參考资料)
  • 我也谈谈《驳“永远不要对一个外行聊你的专业”【十全十美】》
  • iOS 界面 之 EALayout 无需反复编译,可视化实时界面,告别Storyboard AutoLayout Xib等等烦人的工具...
  • windows 7 启用虚拟Wifi 热点网络只需3步搞定
  • hibernate将enum映射成int或varchar类型
  • 如果一个按钮被覆盖如何响应?
  • SEO优化的黑帽手法是否值得使用?
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • 【面试系列】之二:关于js原型
  • angular2开源库收集
  • centos安装java运行环境jdk+tomcat
  • conda常用的命令
  • Javascript 原型链
  • JavaScript中的对象个人分享
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • tweak 支持第三方库
  • 百度地图API标注+时间轴组件
  • 给Prometheus造假数据的方法
  • 京东美团研发面经
  • 经典排序算法及其 Java 实现
  • 批量截取pdf文件
  • 普通函数和构造函数的区别
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 深度解析利用ES6进行Promise封装总结
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • ​力扣解法汇总946-验证栈序列
  • # .NET Framework中使用命名管道进行进程间通信
  • (20050108)又读《平凡的世界》
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (2015)JS ES6 必知的十个 特性
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (pojstep1.1.2)2654(直叙式模拟)
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (搬运以学习)flask 上下文的实现
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (十六)一篇文章学会Java的常用API
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • .net与java建立WebService再互相调用
  • .Net中间语言BeforeFieldInit
  • @Import注解详解
  • @RequestBody的使用
  • @value 静态变量_Python彻底搞懂:变量、对象、赋值、引用、拷贝