条件变量

生产者-消费者设计模式

▼魔方 西西 提交于 2019-12-10 03:02:59
一、生产者消费者设计模式 1、中间队列 一段内存空间,且可存取; 2、两种角色 (1)生产者:生产数据; (2)消费者:消费数据。 3、三种关系 (1)生产者与生产者的互斥关系; (2)消费者与消费者的互斥关系; (3)生产者与消费者的互斥且同步关系。 二、实现方式 1、使用synchronized(wait()和notify()) 2、使用Lock实现(await()和signal()) 3、阻塞队列实现 三、生产者-消费者模型的优点 1、解耦:降低生产者和消费之间的依赖关系 2、支持并发 即生产者和消费者是两个可以独立的并发主体,互不干扰的运行,如果没有中间的环节,则会生产者阻塞或者消费者阻塞。不管是哪种方法效率都比较低。 3、支持盲闲不均 如果生产数据的速度时快时慢,缓冲区可以对其进行适当缓冲。当生产的数据太块时,消费者来不及处理,未处理的数据可以暂时存在缓冲区。等生产者的生产速度慢下来,消费者再慢慢处理掉。 四、提升与思考 1、队列可以有多种实现: (1)先放先出:FIFO (2)后放先出:LIFO (3)优先级队列:Priority Queue 2、为什么生产和消费要用多线程 单线程太耗时,只有当多线程的效率提升可以抵消开发难度和性能消耗时才有必要用多线程; 3、别忘记sychronized和notifyAll() 否则其他线程一直等待,不会继续 4

C++11 并发编程教程

落爺英雄遲暮 提交于 2019-12-06 12:21:59
上一篇文章中我们学习了如何使用互斥量来解决一些线程同步问题。这一讲我们将进一步讨论互斥量的话题,并向大家介绍 C++11 并发库中的另一种同步机制 —— 条件变量。 递归锁 考虑下面这个简单类: 1 2 3 4 5 6 7 8 9 10 11 12 13 struct Complex { std::mutex mutex; int i; Complex() : i(0) {} void mul(int x){ std::lock_guard<std::mutex> lock(mutex); i *= x; } void div(int x){ std::lock_guard<std::mutex> lock(mutex); i /= x; } }; 现在你想添加一个操作以便无误地一并执行上述两项操作,于是你添加了一个函数: 1 2 3 4 5 void both(int x, int y){ std::lock_guard<std::mutex> lock(mutex); mul(x); div(y); } 让我们来测试这个函数: 1 2 3 4 5 int main(){ Complex complex; complex.both(32, 23); return 0; } 如果你运行上述测试,你会发现这个程序将永远不会结束。原因很简单,在 both() 函数中,线程将申请锁

线程同步

你。 提交于 2019-12-06 12:14:21
我们使用互斥锁解决了多个线程的竞态条件问题。 互斥锁的一个主要特点是,谁先拿到锁先就可以优先访问共享资源,因此多个线程访问共享资源的互斥性是得到了保证,但是在某些场合可能还希望确保线程间执行的顺序。 如我们有一个共享内存数据资源M,我们整个程序设计需求是要求线程A在M上做了处理之后,线程B才能做处理。这种需要确保多线程间执行先后顺序的技术,称为线程的同步。 条件变量是线程同步的主要手段。其大致的实现思想就是: 线程B,调用条件变量的接口让自身阻塞; 线程A,在处理完资源后,通过条件变量接口唤醒正在等待该资源的线程B。 条件变量的初始化也有静态初始化和动态初始化两种方式。 //静态初始化 // 与互斥锁类似静态初始化一个全局的条件变量 pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //动态初始化 #include <pthread.h> int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); //通知和等待条件变量 #include <pthread.h> // 等待一个指定的条件变量 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); //

linux中c多线程同步方法

我只是一个虾纸丫 提交于 2019-12-06 02:53:54
https://blog.csdn.net/jkx01whg/article/details/78119189 Linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和信号量。 一、互斥锁(mutex)   锁机制是同一时刻只允许一个线程执行一个关键部分的代码。 1. 初始化锁   int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr); 其中参数 mutexattr 用于指定锁的属性(见下),如果为NULL则使用缺省属性。 互斥锁的属性在创建锁的时候指定,在LinuxThreads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。当前有四个值可供选择: (1)PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。 (2)PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。 (3)PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁

第30课 线程同步(std::condition_variable)

两盒软妹~` 提交于 2019-12-05 01:20:36
一. 条件变量 (一)条件变量概述   多线程访问一个共享资源(或称临界区),不仅需要用互斥锁实现独享访问避免并发错误,在获得互斥锁进入临界区后,还需检查特定条件是否成立。当某个线程修改测试条件后,将通知其它正在等待条件的线程继续往下执行。   1. wait 线程 :如果不满足该条件,拥有条件变量的 wait线程会先释放该互斥锁 ,并把自身放入条件变量内部的等待队列, 阻塞等待条件成立 。   2. notify 线程 :在wait线程阻塞期间,notify线程获取互斥锁并进入临界区内访问共享资源,然后改变测试条件,当条件满足时通知在条件变量上等待的wait线程。wait线程重新申请对该互斥锁加锁,确认条件成立后则进行后续的任务处理,否则继续等待。 (二)std::condition_variable class condition_variable { // class for waiting for conditions public: using native_handle_type = _Cnd_t; condition_variable() { // 默认构造函数 _Cnd_init_in_situ(_Mycnd()); } ~condition_variable() noexcept { // 析构函数 _Cnd_destroy_in_situ(_Mycnd());

02C++条件变量

拥有回忆 提交于 2019-12-04 10:28:34
1. 条件变量 ​ 多线程编程中,等待由另一个线程触发一个时间的最基本机制是条件变量。从概念上说,条件变量与某些事件或其他条件相关,而且一个或多个线程可以等待该条件被满足。当某个线程已经确定条件得到满足,它就可以通知一个或多个正在条件变量上进行等待的线程,以便唤醒它们并让它们继续处理。 #pragma once #pragma execution_character_set("utf-8") #include <iostream> #include <chrono> #include <ctime> #include <iomanip> #include <string> #include <thread> #include <mutex> #include <condition_variable> #include <list> using namespace std; //下面的例子,一个条件变量值用于控制两个线程运行的先后顺序。 //getData线程wait中先阻塞条件变量,等到putData线程中发送通知时,wait解除阻塞,向下运行。 std::mutex mut; std::condition_variable data_cond; std::list<int> data_list; const int g_count = 11; void putData() {

多线程程序设计技术(原理篇)

£可爱£侵袭症+ 提交于 2019-12-04 01:46:49
基本概念 线程:是指一些相关指令的离散序列。线程与其他指令序列的执行相互独立。 线程层次: 用户级线程:在应用软件中所创建和操纵的线程。 内核级线程:操作系统实现大多数线程的方式。 硬件线程:线程在硬件执行资源上的表现形式。 三个层次关系是,开发人员在用户级线程进行设计编码(调用线程库API),操作系统在内核级进行线程管理,并完成软件线程到硬件线程的映射工作。 2.核心理论 多线程程序设计基本思想 三种问题分解方式: 任务分解:不同的程序行为采用不同的线程实现。是对问题域进行纵向切割。 数据分解: 多个线程对不同的数据块执行相同的操作。是对问题域进行横向切割。(将需要进行相同处理大块数据分成小块并行处理) 数据流分解:一个线程的输出作为另一个线程的输入。(即流水线模型) 同步理论 同步是对线程执行的顺序进行强行限制的一种机制,用来控制线程执行的相对顺序。 同步一般通过三种原语实现: 信号量 经典P,V操作理论,典型应用为保护至多允许n个请求并行访问的共享资源。 锁 锁可以看成信号量的的一个特殊实现。目前主要有4中类型: 互斥量 (Mutex):最简单的锁类型。互斥量的释放一般需要引入定时器实现来保证健壮性。 递归锁 (Recursive Lock):递归需哦是指可以被当前持有该锁的线程重复获取,而不会导致该线程产生死锁的所类型(防止递归死锁) 读写锁 (Read-Write

C++标准库之condition_variable(条件变量)

匿名 (未验证) 提交于 2019-12-03 00:32:02
是C++ 标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时表示条件变量的类与方法等。 或称临界区)时,不但需要用互斥锁实现独享访问以避免并发错误(称为竞争危害),在获得互斥锁进入临界区后还需要检验特定条件是否成立: (1) 、如果不满足该条件,拥有互斥锁的线程应该释放该互斥锁,把自身阻塞(block) 并挂到(suspend)条件变量的线程队列中 (2) 、如果满足该条件,拥有互斥锁的线程在临界区内访问共享资源,在退出临界区时通知(notify) 在条件变量的线程队列中处于阻塞状态的线程,被通知的线程必须重新申请对该互斥锁加锁。 的标准库中新增加的条件变量的实现,与pthread 的实现语义完全一致。使用条件变量做并发控制时,某一时刻阻塞在一个条件变量上的各个线程应该在调用wait操作时指明同一个互斥锁,此时该条件变量与该互斥锁绑定;否则程序的行为未定义。条件变量必须与互斥锁配合使用,其理由是程序需要判定某个条件(condition或称predict)是否成立,该条件可以是任意复杂。 离开临界区的线程用notify操作解除阻塞(unblock)在条件变量上的各个线程时,按照公平性(fairness)这些线程应该有平等的获得互斥锁的机会,不应让某个线程始终难以获得互斥锁被饿死(starvation),并且比后来到临界区的其它线程更为优先(即基本上FIFO)

C++多线程的基本使用

匿名 (未验证) 提交于 2019-12-03 00:21:02
C++11增加了线程及线程相关的累,很方便的支持了并发编程,使得编写的多线程程序的可移植性得到了很大的提高. 线程的创建 用std::thread 创建线程非常的简单,只需要提供线程函数或者函数对象即可,并可以同时指定线程的参数: #include<iostream> #include<thread> #include<chrono> using namespace std ; //线程函数 void func( int a, int b, int c) { std ::this_thread::sleep_for( std ::chrono::seconds( 3 )); cout << a << " " << b << " " << c << endl; } int main() { //创建线程对象t1,绑定线程函数为func std ::thread t1(func, 1 , 2 , 3 ); //输出t1的线程ID std :: cout << "ID:" << t1.get_id() << std ::endl; //等待t1线程函数执行结束 t1.join(); std ::thread t2(func, 2 , 3 , 4 ); //后台执行t2的线程函数,并且不会因为main函数结束时,线程函数未执行完而产生异常 t2.detach(); cout <<

Linux线程唤醒与等待

匿名 (未验证) 提交于 2019-12-02 21:56:30
生产者消费者模式在程序设计中出现频率非常高,经常会有线程间通过消息队列或其他共享变量进行交互的场景。而这时就会出现一个问题,消费者如何知道生产者已经生产了数据呢?有的程序会采取消费者循环判断消息队列大小是否为0,如果不为0则取出数据之类的方法。但是该种方法带来两个问题: 1. 生产者产出数据到消费者获得数据的延时较大。 2. CPU占用较高。 如果需要降低延时,则必然要提高轮询的频率,那么CPU占用就会升高。反之亦然,两者无法同时解决。 于是,唤醒等待机制就成为适合该种场景的解决方案。 该机制需要一个互斥对象以及条件变量共同完成,如下: pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex; 其中条件变量使用宏结构常量进行赋值。接下来进行互斥对象与条件变量的初始化: pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); 生产者唤醒逻辑: pthread_mutex_lock(&mutex); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); 消费者等待逻辑: pthread_mutex_lock(&mutex); pthread_cond_wait(