相关文章推荐
开朗的毛衣  ·  OpenHarmony ...·  1 年前    · 
痴情的啄木鸟  ·  electron ...·  1 年前    · 

首先关于条件变量的引入:

假想在这样的情况下,多个线程需要等待某个条件才能继续工作(如生产者消费者模型中,消费者需要等待流水线上有产品后才能消费),如果只使用互拆锁,则多个线程要不停的查询流水线是否为空这个状态,并且查询这个操作需要加入临界区,因为流水线不仅同时有多个消费者,还有生产者在生产,不加锁的话可能出现两个甚至多个消费者对同一个产品动手的情况。这种不停查询的操作是很蠢的,因此引入了条件变量,在查询条件不满足的情况下线程休眠,让出CPU。

为什么要传入互斥锁,与互斥锁配套使用?

首先,条件本身就是公共资源,如流水线的状态,因此必须使用互斥锁在临界区内对条件进行保护。

其次,pthread_cond_wait()操作实际上分为两步,第一步将线程挂在等待条件的线程列表上,然后对互斥锁解锁。

如果不传入这个互斥锁,实际上流程变为:

2.判断流水线状态

4.挂起线程

则在3与4间非原子,如果在3之后生产者线程生产了一个产品并进行了notify,而notify结束后这个消费者线程才挂起,则这个notify丢失了,只有生产者再生产一个产品才会唤醒它,如果只有一个消费者的话则这个notify完全丢失,如果有多个消费者则还可能被其他消费者所捕获,但逻辑上出现了问题。

为什么会出现虚假唤醒,为什么要用while来避免虚假唤醒?

虚假唤醒的出现在于生产者的notify并不在临界区内,也就是说,生产者使用临界区保护了修改流水线的这个操作,然后解锁,解锁完毕后才notify。而在这之间是非原子的。

在以下情况:

1).生产者对临界区加锁

2).修改流水线状态

3).生产者解锁

4).notify通知生产者线程

在3)与4)间是有空隙的,如果在3)进行后突然此刻加入了一个新的生产者,这个生产者察觉到流水线的变化,对他进行了消费,然后消费者才notify,notify唤醒了原有的消费者, 但流水线已经为空了,实际上这就是一个虚假唤醒,唤醒后并无工作可做。

因此不能用if来进行条件判断,加入while就可以避免虚假唤醒,在每次唤醒后先判断流水线条件,这样避免了虚假唤醒的情况。

做过稍微大一点项目的人都知道,力求程序的稳定性和调度的方便, 使用 了大量的线程,几乎每个模块都有一个专门的线程处理函数。而互斥量与 条件变量 在线程管理中必不可少,任务间的调度几乎都是由互斥量与 条件变量 控制。互斥量的实现与进程中的信号量(无名信号量)是类似的,当然,信号量也可以用于线程,区别在于初始化的时候,其本质都是P/V操作。编译时,记得 上-lpthread或-lrt哦。    有关进程间通信(消息队列)见:进程间通信之深入消息队列的详解 一、互斥量 1. 初始化与销毁:    对于静态分配的互斥量, 可以初始化为PTHREAD_MUTEX_INITIALIZER(等价于pthread_mut **Linux中帮助中提到:**在多核处理器下,pthread_cond_signal可能会激活多于一个线程(阻塞在 条件变量 上的线程)。结果是,当一个线程调用pthread_cond_signal()后,多个调用pthread_cond_wait()或pthread_cond_timedwait()的线程返回。这种效应成为” 虚假 唤醒 。虽然 虚假 唤醒 在pthread_cond_wait函数中可以解决,为了发生概率很低的情况而降低边缘条件,效率是不值得的,纠正这个问题会降低对所有基于它的所有更高级的同步操作的并发 如果是多个线程都在等待这个条件,而同时只能有一个线程进行处理,此时就必须要再次条件判断,以使只有一个线程进入临界区处理。 这里做了个实验来说明:我用到两个消费者一个生产者,判定条件是当队列不为空时发信号,消费者满足条件,开始消费时先打印队列的大小,然后pop一个产品。通过观察打印的队列大小来验证为什么需要再次判断。while时:#include &lt;stdio.h&gt; #include &... 此文是linux c++的一个程序,该程序要求是给定一个缓冲区,一个生产者,一个消费者,然后要求 使用 条件变量 ,互斥量来解决读写问题,其中有个重要的知识点就是, 使用 信号量的时候,如何保证线程安全,如果有一个生产者,多个消费者,这种情况下, 条件变量 wait地方就应该 使用 while,而非if,如果是单生产单消费,则可以用if。具体解释见代码注释 /* ex7-4.c */ #include 接上篇:C++新特性35_ 条件变量 的引入(传统采用while(1)的轮询方式解决线程按顺序执行和共享变量问题十分低效, 使用 条件变量 可以实现高效的事件模型(类似于Qt中信号槽机制))引入了 条件变量 ,用于线程间数据交互或者线程间存在先后顺序的情况,本篇将介绍如何 使用 条件变量 条件变量 在C1. 条件变量 的用法 下为利用C++11中 条件变量 的代码: #include <iostream> #include <string> #include <mutex> #include & 条件变量 (cond)使在多线程程序中用来实现“等待---> 唤醒 ”逻辑常用的方法,是进程间同步的一种机制。 条件变量 用来阻塞一个线程,直到条件满足被触发为止,通常情况下 条件变量 和互斥量同时 使用 。一般 条件变量 有两个状态:(1)一个/多个线程为等待“ 条件变量 的条件成立“而挂起;(2)另一个线程在“ 条件变量 条件成立时... LinkedBlockingQueue LinkedBlockingQueue是基于链表的阻塞FIFO队列,可以指定一个最大的长度限制以防止过度扩展,未指定情况下其大小为Integer.MAX_VALUE;提供比ArrayBlockingQueue更高的吞吐量但是在高并发条件下可预测性降低。 JAVA多线程和并发 文章目录JAVA多线程和并发多线程RunnableCallableThread线程同步竞争状态线程安全临界区java在处理线程同步时常用方法volatile关键字Java内存模型并发编程的三大概念:原子性,有序性,可见性原子性可见性volatile保证可见性volatile不能确保原子性volatile保证有序性synchronized关键字线程不安全的例子synchronized 修饰方法synchronized 修饰代码块wait notifyLock下的 Condition 的a 一、定义: 1.1、解释: 条件变量 是利用线程间共享的变量进行同步的一种机制,是在多线程程序中用来实现"等待–> 唤醒 "逻辑常用的方法,用于维护一个条件(与是 条件变量 不同的概念),线程可以 使用 条件变量 来等待某个条件为真,注意理解并不是等待 条件变量 为真。 当条件不满足时,线程将自己 入等待队列,同时释放持有的 互斥锁 ; 当一个线程 唤醒 一个或多个等待线程时,此时条件不一定为真( 虚假 唤醒 )。 1.2、个人理解: 两个线程利用 条件变量 互斥锁 实现同步。 条件变量 互斥锁 对两个线程来说是全局的。 一个线程利用条件变