c++多线程

c++多线程

一、线程创建

1.1 创建线程

线程头文件 thread

1
2
3
4
5
6
7
std::thread thread([]{
while(true){
std::cout<<std::this_thread::get_id()<<'\n';
std::this_thread::sleep_for(std::chrono::microseconds(50));
}
});//创建线程
thread.join();//等待线程结束

1.2 互斥量、原子变量

互斥量头文件 mutex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
std::mutex mtx;
int sum=0;
auto f=[&](){
for(int i=0;i<1000000;++i){
mtx.lock();
++sum;
--sum;
mtx.unlock();
}
};
std::thread thread1(f);
std::thread thread2(f);
thread1.join();
thread2.join();
std::cout<<sum<<'\n';

使用std::lock_guard实现自动上锁解锁(RAII),生命周期是作用域

1
2
3
std::lock_guard<std::mutex> lock(mtx);
++sum;
--sum;

使用std::unique_lock可以手动关锁

1
2
3
4
std::unique_lock<std::mutex> lock(mtx);
++sum;
--sum;
lock.unlock();

原子变量头文件 atmoic

1
2
3
4
5
6
7
std::atomic<int> sum=0;
auto f=[&](){
for(int i=0;i<1000000;++i){
++sum;
--sum;
}
};

1.3 条件变量、信号量

条件变量头文件 condition_variable
cv.wait(lock);执行时会先释放锁,等被notify通知后会再次获取锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<bits/stdc++.h>

std::condition_variable cv;
std::mutex mtx;
std::queue<int>q;
void task1(){
int i=0;
while(true){
std::unique_lock<std::mutex> lock(mtx);
q.push(i);
cv.notify_one();
if(i<999999){
i++;
}else{
i=0;
}
}
}
void task2(){
int data=0;
while(true){
std::unique_lock<std::mutex> lock(mtx);
while(q.empty()){
/*此处必须是while,如果为if会导致
虚假唤醒,因为thread2在被唤醒后等
待thread3释放锁,此时队列只有一个
元素被thread3将它拿走,导致队列为空*/
cv.wait(lock);
}
data=q.front();
q.pop();
std::cout<<"get "<<data<<std::endl;
}
}
int main(){
std::thread thread1(task1);
std::thread thread2(task2);
std::thread thread3(task2);
thread1.join();
thread2.join();
thread3.join();
}

信号量头文件 semaphore

1
2
3
4
5
6
7
8
9
10
11
12
std::counting_semaphore<6>csem(0);//最大值为6
std::binary_semaphore bsem(0);//最大为1
void task(){
std::cout<<"start\n";
csem.acquire();
std::cout<<"end\n";
}
int main(){
std::thread thread1(task);
csem.release(5);
thread1.join();
}

1.4 promise future

头文件 future

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void task(int a,int b,std::promise<int>& ret){
a*=a;
b*=2;
ret.set_value(a+b);
}
int main(){
std::promise<int> p;
std::future<int> f=p.get_future();
std::thread t(task,1,2,std::ref(p));
std::cout<<f.get()<<'\n';
//get会等待set_value操作
//future只能get一次,要使用多次可以使用shared_future
t.join();
}

1.5 std::packaged_task std::async

async使用

1
2
3
4
5
6
7
8
9
10
11
12
int task(int a,int b){
a*=a;
b*=2;
return a+b;
}
int main(){
std::future<int> f=std::async(std::launch::async,task,1,2);
//直接开启一个线程计算
// std::future<int> f=std::async(std::launch::deferred,task,1,2);
//等到get时再计算(默认为deferred)
std::cout<<f.get()<<'\n';
}

paskaged_task使用

1
2
3
4
5
6
7
8
9
10
11
12
int task(int a,int b){
a*=a;
b*=2;
return a+b;
}
int main(){
std::packaged_task<int(int,int)> t(task);
// std::packaged_task<int(int,int)> t(std::bind(task,1,2));
//将参数绑定,后续直接t()调用
t(1,2);
std::cout<<t.get_future().get()<<'\n';
}