多线程
一般使用方法
atomic
原子类型 一般运用于变量 本身相当于有自动锁
atomic<bool> b(true);
b = false;
thread_local
thread_local 定义的变量在每个线程都保存一份副本,互不干扰在线程退出时候自动销毁
thread_local int g_k = 0
detch与join
主进程与线程分离detach()后子线程在后台独立继续运行,
主线程无法再取得子线程的控制权,即使主线程结束,子线程未执行也不会结束。
当主线程结束时,由运行时库负责清理与子线程相关的资源。
实际应用如让一个文字处理应用同时编辑多个文档,让每个文档处理窗口拥有自己的线程,
每个线程运行同样的代码,并隔离不同窗口处理的数据
join当前线程完成退出后才能继续下一个线程或者继续主线程
线程传入可修改的参数
projects5
void proc(int &a){
a = a+100;
cout<<"a = "<<a<<endl;
cout<<"thread_id = "<<std::this_thread::get_id()<<endl;
}
bind与thread传递引用时必须外层使用ref来进行传递
int a=9;
thread th2(proc,ref(a));
//主线程等待子线程运行完之后才继续运行
th2.join();
结果
lock_guard< mutex >超过使用范围自动解锁
void proc1(int a){
//m.lock();
lock_guard<mutex> g1(m);
cout<<"proc1 change a"<<endl;
cout<<"proc1 before a = "<<a<<endl;
a = a+2;
cout<<"proc1 after a = "<<a<<endl;
//cout<<"proc1 thread_id = "<<std::this_thread::get_id()<<endl;
//m.unlock();
}
void proc2(int a){
//m.lock();
{
lock_guard<mutex> g2(m);//用大括号限制锁的范围
cout<<"proc2 change a"<<endl;
cout<<"proc2 before a = "<<a<<endl;
a = a+4;
cout<<"proc2 after a = "<<a<<endl;
//cout<<"proc2 thread_id = "<<std::this_thread::get_id()<<endl;
//m.unlock();
}
cout<<"beyond 2"<<endl;
cout<<"beyond 3"<<endl;
}
thread th2(proc2,a);
thread th1(proc1,a);
th1.join();
th2.join();
结果
锁一旦放出,则后续输出顺序不定
各种锁的方式
defer_lock
void proc3(int a){
unique_lock<mutex> g1(m,defer_lock);//初始化了一个没有加锁的mutex
g1.lock();//使用g1进行m的管理,在这抢赢了4 但是输出顺序乱了
cout<<"xxxxxxxxxx"<<endl;
//g1.lock(); //在这抢不过4
cout<<"proc3 change a"<<endl;
cout<<"proc3 before a = "<<a<<endl;
a = a+3;
cout<<"proc3 after a = "<<a<<endl;
//cout<<"proc1 thread_id = "<<std::this_thread::get_id()<<endl;
//m.unlock();
}//自动释放锁
try_to_lock
尝试加锁如果没有锁定成功会立即返回,失败后不会阻塞线程,而是继续往下执行
void proc4(int a){
unique_lock<mutex> g2(m,try_to_lock);
if(g2.owns_lock()){
cout<<"proc4 change a"<<endl;
cout<<"proc4 before a = "<<a<<endl;
a = a+4;
cout<<"proc4 after a = "<<a<<endl;
}
else {
cout<<"beyond 4"<<endl;
cout<<"beyond 5"<<endl;
}
}//自动解锁
adopt_lock
void proc5(int a){
m.lock();
//收养锁,托管锁,发生异常也不会没有解锁而产生死锁
lock_guard<mutex> g5(m,adopt_lock);
cout<<"proc5 change a"<<endl;
cout<<"proc5 before a = "<<a<<endl;
a = a+5;
cout<<"proc5 after a = "<<a<<endl;
}
thread th5(proc5,a);
thread th3(proc3,a);
thread th4(proc4,a);
th5.join();
th3.join();
th4.join();
结果
由于try_to_lock的存在,所以并没有完全按照顺序执行 p4的语句混在里面
异步线程
异步线程 凭借future对象进行get()结果,如果结果没出子线程没有return 就一直阻塞
double proc6(const double &a,const double &b){
double c = a + b;
_sleep(3000);
return c;
}
//生产者
void producer(){
int data1;
while(1){
if(c<3)//限制产品数量
{
{
data1 = rand();
unique_lock<mutex> locker(m);//锁
q.push_front(data1);
cout<<"message is pushed"<<endl;
cond.notify_one();//唤醒任意一个等待的线程
++c;
}//锁的范围
_sleep(500);
}
}
}
future
double a1 = 2.3;
double b1 = 6.7;
future<double> fu = async(proc6,a1,b1);
cout<<"the result is doing"<<endl;
cout<<"waiting for a while"<<endl;
cout<<"result is : "<<fu.get()<<endl;//阻塞主线程,直至异步线程return
结果
一直等待到子线程出结果
shared_future
可以get多次
shared_future<double> fu = async(proc6,a1,b1);
cout<<"the result is doing"<<endl;
cout<<"waiting for a while"<<endl;
cout<<"result is : "<<fu.get()<<endl;//阻塞主线程,直至异步线程return
cout<<"result is : "<<fu.get()<<endl;//阻塞主线程,直至异步线程return
结果
生产者和消费者
生产者
//生产者
void producer(){
int data1;
while(1){
if(c<3)//限制产品数量
{
{
data1 = rand();
unique_lock<mutex> locker(m);//锁
q.push_front(data1);
cout<<"message is pushed"<<endl;
cond.notify_one();//唤醒任意一个等待的线程
++c;
}//锁的范围
_sleep(500);
}
}
}
消费者
wait(unique_lock) wait会自动释放锁,并阻塞当前线程,当被唤醒时自动调用lock上锁
void consumer1(){
int data2;
while(1){
{
unique_lock<mutex> locker(m);
while (q.empty())
{
cond.wait(locker);//阻塞前会先解锁
}
data2=q.back();
q.pop_back();
cout<<"consumer1 get message"<<endl;
--c;
}//上锁的范围
_sleep(600);
}
}
void consumer2(){
int data2;
while(1){
{
unique_lock<mutex> locker(m);
while (q.empty())
{
cond.wait(locker);//阻塞前会先解锁
}
data2=q.back();
q.pop_back();
cout<<"consumer2 get message"<<endl;
--c;
}//上锁的范围
_sleep(700);
}
}
void consumer3(){
int data2;
while(1){
{
unique_lock<mutex> locker(m);
while (q.empty())
{
cond.wait(locker);//阻塞前会先解锁
}
data2=q.back();
q.pop_back();
cout<<"consumer3 get message"<<endl;
--c;
}//上锁的范围
_sleep(1500);
}
}
结果