c++ linux 线程等待与唤醒_C++并发编程 等待与唤醒
C++并发编程 等待与唤醒
条件变量
条件变量, 包括(std::condition_variable 和 std::condition_variable_any)
定义在 condition_variable 头文件中, 它们都需要与互斥量(作为同步工具)一起才能工作.
std::condition_variable 允许阻塞一个线程, 直到条件达成.
成员函数
void wait(std::unique_lock<:mutex>& lock);
等待, 通过 notify_one(), notify_all()或伪唤醒结束等待
void wait(std::unique_lock<:mutex>& lock, Predicate pred);
等待, 通过 notify_one(), notify_all()被调用, 并且谓词为 true 时结束等待.
pred 谓词必须是合法的, 并且需要返回一个值, 这个值可以和bool互相转化
cv_status wait_until(std::unique_lock<:mutex>& lock, const std::chrono::time_point& absolute_time);
调用 notify_one(), notify_all(), 超时或线程伪唤醒时, 结束等待.
返回值标识了是否超时.
bool wait_until(std::unique_lock<:mutex>& lock, const std::chrono::time_point& absolute_time, Predicate pred);
等待, 通过 notify_one(), notify_all(), 超时, 线程伪唤醒, 并且谓词为 true 时结束等待.
cv_status wait_for(std::unique_lock<:mutex>& lock, const std::chrono::duration& relative_time);
调用 notify_one(), notify_all(), 指定时间内达成条件或线程伪唤醒时,结束等待
bool wait_for(std::unique_lock<:mutex>& lock, const std::chrono::duration& relative_time, Predicate pred);
调用 notify_one(), notify_all(), 指定时间内达成条件或线程伪唤醒时,并且谓词为 true 时结束等待.
void notify_one() noexcept; 唤醒一个等待当前 std::condition_variable 实例的线程
void notify_all() noexcept; 唤醒所有等待当前 std::condition_variable 实例的线程
一个线程安全的队列设计:
#ifndef _THREAD_SAFE_QUEUE_#define _THREAD_SAFE_QUEUE_#include#include#include#includetemplate
classThreadSafeQueue
{
typedef std::queueQueue;
typedef std::shared_ptrSharedPtr;
typedef std::lock_guardMutexLockGuard;
typedef std::unique_lockMutexUniqueLock;public:explicitThreadSafeQueue() {}~ThreadSafeQueue() {}
ThreadSafeQueue(const ThreadSafeQueue&) = delete;
ThreadSafeQueue& operator=(const ThreadSafeQueue&) = delete;bool IsEmpty() const{
MutexLockGuard lk(mMutex);returnmQueue.empty();
}void WaitAndPop(Ty&value)
{
MutexUniqueLock lk(mMutex);
mConVar.wait(lk, [this] {return !mQueue.empty();
});
value=mQueue.front();
mQueue.pop();
}
SharedPtr WaitAndPop()
{
MutexUniqueLock lk(mMutex);
mConVar.wait(lk, [this] {return !mQueue.empty();
});
SharedPtr sp= std::make_shared(mQueue.front());
mQueue.pop();returnsp;
}bool TryPop(Ty&value)
{
MutexLockGuard lk(mMutex);if (mQueue.empty())return false;
value=mQueue.front();
mQueue.pop();return true;
}
SharedPtr TryPop()
{
MutexLockGuard lk(mMutex);if (mQueue.empty())return false;
SharedPtr sp= std::make_shared(mQueue.front());
mQueue.pop();returnsp;
}void Push(const Ty&value)
{
MutexLockGuard lk(mMutex);
mQueue.push(value);
mConVar.notify_all();
}private:
mutable Mutex mMutex;
ConditionVar mConVar;
Queue mQueue;
};#endif //_THREAD_SAFE_QUEUE_
另一个版本, 使用 shared_ptr 作为成员对队列的性能有很大的提升, 其在push时减少了互斥量持有的时间, 允许其它线程在分配内存的同时,对队列进行其它操作.
template
classThreadSafeQueue
{
typedef std::shared_ptrSharedPtr;
typedef std::queueQueue;
typedef std::shared_ptrSharedPtr;
typedef std::lock_guardMutexLockGuard;
typedef std::unique_lockMutexUniqueLock;public:explicitThreadSafeQueue() {}~ThreadSafeQueue() {}
ThreadSafeQueue(const ThreadSafeQueue&) = delete;
ThreadSafeQueue& operator=(const ThreadSafeQueue&) = delete;bool IsEmpty() const{
MutexLockGuard lk(mMutex);returnmQueue.empty();
}void WaitAndPop(Ty&value)
{
MutexUniqueLock lk(mMutex);
mConVar.wait(lk, [this] {return !mQueue.empty();
});
value= std::move(*mQueue.front());
mQueue.pop();
}
SharedPtr WaitAndPop()
{
MutexUniqueLock lk(mMutex);
mConVar.wait(lk, [this] {return !mQueue.empty();
});
SharedPtr sp=mQueue.front();
mQueue.pop();returnsp;
}bool TryPop(Ty&value)
{
MutexLockGuard lk(mMutex);if (mQueue.empty())return false;
value= std::move(*mQueue.front());
mQueue.pop();return true;
}
SharedPtr TryPop()
{
MutexLockGuard lk(mMutex);if (mQueue.empty())return false;
SharedPtr sp=mQueue.front();
mQueue.pop();returnsp;
}void Push(const Ty&value)
{
SharedPtr p= std::make_shared(value);
MutexLockGuard lk(mMutex);
mQueue.push(p);
mConVar.notify_all();
}private:
mutable Mutex mMutex;
ConditionVar mConVar;
Queue mQueue;
};
std::future
期望(std::future)可以用来等待其他线程上的异步结果, 其实例可以在任意时间引用异步结果.
C++包括两种期望, std::future(唯一期望) 和 std::shared_future(共享期望)
std::future 的实例只能与一个指定事件相关联.
std::shared_future 的实例能关联多个事件, 它们同时变为就绪状态, 并且可以访问与事件相关的任何数据.
在与数据无关的地方,可以使用 std::future 与 std::shared_future 的特化模板.
期望对象本身并不提供同步访问, 如果多个线程要访问一个独立的期望对象, 需要使用互斥体进行保护.
std::packaged_task
std::packaged_task 可包装一个函数或可调用的对象, 并且允许异步获取该可调用对象产生的结果, 返回值通过 get_future 返回的 std::future 对象取得, 其返回的 std::future 的模板类型为 std::packaged_task 模板函数签名中的返回值类型.
std::packaged_task 对象被调用时, 就会调用相应的函数或可调用对象, 将期望置为就绪, 并存储返回值.
std::packaged_task 的模板参数是一个函数签名, 如 int(std::string&, double*), 构造 std::packaged_task 实例时必须传入一个可以匹配的函数或可调用对象, 也可以是隐藏转换能匹配的.
std::packaged_task<:string std::string> task([](std::stringstr) {
std::stringstream stm;
stm<< "tid:" << std::this_thread::get_id() << ", str:" << str <<:endl>
std::cout<
std::this_thread::sleep_for(std::chrono::seconds(1));return std::string("MSG:Hello");
});
std::future<:string> f =task.get_future();
std::thread t(std::move(task), std::string("package task test"));
t.detach();//调用 f.get 返回结果, 但是须阻塞等到任务执行完成
std::cout << "main tid:" << std::this_thread::get_id() << ", result:" << f.get() << std::endl;
std::promise
std::promise 类型模板提供设置异步结果的方法, 这样其他线程就可以通过 std::future 实例来索引该结果.
classSquareRoot
{
std::promise&prom;public:
SquareRoot(std::promise&p) : prom(p) {}~SquareRoot() {}void operator()(doublex)
{if (x < 0)
{
prom.set_exception(std::make_exception_ptr(std::out_of_range("x<0")));
}else{double result =std::sqrt(x);
prom.set_value(result);
}
}
};
std::promiseprom;
SquareRoot p(prom);
std::thread t(std::bind(&SquareRoot::operator(), &p, 1));//std::thread t(std::bind(&SquareRoot::operator(), &p, -1));
std::future f =prom.get_future();try{double v = f.get();
std::cout<< "value:" << v <<:endl>
}catch (std::exception&e)
{
std::cout<< "exception:" << e.what() <<:endl>
}
t.join();
c++ linux 线程等待与唤醒_C++并发编程 等待与唤醒相关推荐
- 判断线程是否执行完毕_Java并发编程 | 线程核心机制,基础概念扩展
源码地址:GitHub || GitEE 一.线程基本机制 1.概念描述 并发编程的特点是:可以将程序划分为多个分离且独立运行的任务,通过线程来驱动这些独立的任务执行,从而提升整体的效率.下面提供一个 ...
- java线程同步的实现_Java并发编程(三) - 实战:线程同步的实现
synchronized关键字 首先,来看一个多线程竞争临界资源导致的同步不安全问题. package com.example.weishj.mytester.concurrency.sync; /* ...
- java 等待几秒_Java并发编程synchronized相关面试题总结
说说自己对于synchronized关键字的了解 synchronized关键字用于解决多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个 ...
- winform判断线程有没有完成_并发编程系列1:线程池的架构实现、大小配置、及四种线程池使用...
△ 公众号回复关键词"架构" 即可领取<1500+BAT架构及面试专题合集> 本篇为线程池系列文章之一,不经常使用线程池的童鞋,还有对几种线程的使用不甚了解的童鞋,可以 ...
- python线程唤醒_Python 并发编程(一)之线程
常用用法 t.is_alive() Python中线程会在一个单独的系统级别线程中执行(比如一个POSIX线程或者一个Windows线程) 这些线程将由操作系统来全权管理.线程一旦启动,将独立执行直到 ...
- java等待5秒_Java并发编程-主线程等待子线程解决方案
主线程等待所有子线程执行完成之后,再继续往下执行的解决方案 public class TestThread extends Thread { public void run() { System.ou ...
- java 线程安全的原因_Java并发编程——线程安全性深层原因
线程安全性深层原因 这里我们将会从计算机硬件和编辑器等方面来详细了解线程安全产生的深层原因. 缓存一致性问题 CPU内存架构 随着CPU的发展,而因为CPU的速度和内存速度不匹配的问题(CPU寄存器的 ...
- java线程高并发编程
java线程详解及高并发编程庖丁解牛 线程概述: 祖宗: 说起java高并发编程,就不得不提起一位老先生Doug Lea,这位老先生可不得了,看看百度百科对他的评价,一点也不为过: 如果IT的历史,是 ...
- linux 线程--内核线程、用户线程实现方法
Linux上进程分3种,内核线程(或者叫核心进程).用户进程.用户线程 内核线程拥有 进程描述符.PID.进程正文段.核心堆栈 当和用户进程拥有相同的static_prio 时,内核线程有机会得到更多 ...
最新文章
- 定时调度模块:sched
- eclipse配置了maven,项目报错
- java并发之线程封闭(二)
- kotlin学习之对象(九)
- uniapp动态修改样式_uniapp样式动态绑定
- 变速后没有声音_问答 | 现代朗动at,启动后怠速不稳,热车后正常,是什么问题?...
- 贴片铝电容识别及型号_电容器选型及其应用规范
- 自动驾驶_ROS简介
- kubernetes资源类型和kubectl命令总结
- 高中计算机网络培训心得体会,高中老师信息技术培训心得体会
- C#版TXT文本分割器
- 【盘点】imx6的应用
- 时序分析 29 - 时序预测 - 格兰杰因果关系(下) python实践2
- 什么是邮箱个人签名?邮箱如何设置个人签名?
- Java24种设计模式(第二种)--代理模式(Proxy Pattern)
- android 播放网络Flash视频 ,需要手机已安装Adobe Flash插件
- 计算机英语拆分,如何使用英语单词拆分法
- Word2007 无法复制粘贴的原因以及正确加载mathtype
- 真空压缩袋哪个牌子好
- Docker-java api简介
热门文章
- LPWA技术:发展物联网的最佳选择
- 设计模式系列-创建者模式
- 中毒,重装,杀毒……最近一段时间,很烦的一件事,不断重复……
- MIPI DSI协议介绍
- 【ValueError: Target is multiclass but average=‘binary‘. Please choose another average setting, one 】
- 【图像处理】——Python鼠标框选ROI(感兴趣)区域并且保存(含鼠标事件)
- java实现选择排序 带打印,选择排序算法的JAVA实现
- centos 安装boost(caffe需要)
- python画圆并填充图形颜色_如何使用python设计语言graphics绘制圆形图形
- sunday java_Sunday算法:最快的字符串匹配算法