c++11新特性之多线程总结
一、线程初始化方式
std::thread thread_1(thread1);
if (thread_1.joinable()) thread_1.join();
std::thread thread_2(thread2, 2);
if (thread_2.joinable()) thread_2.join();
std::thread(thread2, 3).detach();
auto lambda = [](int a) {
std::cout << "lambda : " << a << std::endl;
};
std::thread thread_3(thread3, 3);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::thread thread_4(thread4, 4);
std::thread thread_5(lambda, 5);
std::cout << "当前 cpu 个数 " << std::thread::hardware_concurrency() << std::endl;
if (thread_3.joinable())
thread_3.join();
if (thread_4.joinable())
thread_4.join();
if (thread_5.joinable())
thread_5.join();
二、总结
1.detach()是将子线程与主线程分离,成为孤儿线程
2.孤儿线程通信方式:
#include <queue>
std::mutex cv_mutex;
void produceA(std::queue<char>& q) {
std::unique_lock<std::mutex> lock;
for(auto i = 0; i < 10; ++i){
q.push('A');
}
}
void produceB(std::queue<char>& q) {
std::unique_lock<std::mutex> lock;
for (auto i = 0; i < 10; ++i) {
q.push('B');
}
}
int main(){
std::queue<char> q;
std::thread produceA_thread(produceA, ref(q));
produceA_thread.detach();
std::thread produceB_thread(produceB, ref(q));
produceB_thread.detach();
}
3.主线程传递给子线程的对象要用ref(),防止拷贝(特别传入孤儿线程)
4.线程之间共享的数据要加锁,而且是同一把锁
5.如果条件变量用于孤儿线程,主线程不能提前结束,要等待孤儿线程的条件变量通信完成
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <chrono>
std::condition_variable cv;
std::mutex cv_mutex;
void wait() {
std::cout << "waitting..." << std::endl;
std::unique_lock<std::mutex> u_lock(cv_mutex);
cv.wait(u_lock);
std::cout << "wait end" << std::endl;
}
void notify() {
std::cout << "notifying..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
cv.notify_all();
std::cout << "notified" << std::endl;
}
int main(){
std::thread wait_thread(wait);
wait_thread.detach();
std::thread notifiy_thread(notify);
notifiy_thread.detach();
std::this_thread::sleep_for(std::chrono::seconds(3));
return 0;
}
6.多个线程共享的自定义类用智能指针,而且要使用ref()防止拷贝,
7.线程处于阻塞状态时,有一定概率出现虚假唤醒,要使用while来避免
8.信号丢失问题通常出现在线程执行顺序错误
9.std::cout也是要争抢的资源
10.在共享类里面给共享数据加锁,并且要写数据时要加容错处理
11.cv.wait(u_lock,lambda),等待结束的条件是:u_lock收到notify并且lambda返回值为true,一定要两个同时满足!!!!!!!!!!
三、示例:巨多生产者和消费者同时并发
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <queue>
class Queue
{
std::mutex mutex;
std::queue<char> q;
public:
std::condition_variable _consume_cv;
std::condition_variable _produce_cv;
std::mutex _consume_mutex;
std::mutex _produce_mutex;
Queue() {
}
~Queue() {
};
void pushToQueue(const char& a) {
std::unique_lock<std::mutex> u_lock(mutex);
if (10000 == q.size()) return;
std::cout << "produce : A " << std::endl;
q.push(a);
}
void popfromQueue() {
std::unique_lock<std::mutex> u_lock(mutex);
if (q.empty()) return;
std::cout << "consume : " << q.front() << std::endl;
q.pop();
}
size_t getQueueSize() {
return q.size();
}
bool isEmpty() {
return q.empty();
}
char getQueueFront() {
return q.front();
}
};
void produce(std::shared_ptr<Queue>& q) {
if (q == nullptr) {
std::cout << "q is nullptr" << std::endl;
}
while (true)
{
if (10000 <= q->getQueueSize()) {
q->_consume_cv.notify_all();
std::unique_lock<std::mutex> u_lock(q->_produce_mutex);
q->_produce_cv.wait(u_lock);
}
q->pushToQueue('A');
}
}
void consume(std::shared_ptr<Queue>& q) {
if (q == nullptr) {
std::cout << "q is nullptr" << std::endl;
}
while (true)
{
if (q->isEmpty()) {
q->_produce_cv.notify_all();
std::unique_lock<std::mutex> u_lock(q->_consume_mutex);
q->_consume_cv.wait(u_lock);
}
q->popfromQueue();
}
}
int main() {
std::shared_ptr<Queue> q = std::make_shared<Queue>();
std::thread producers[80];
for (auto i = 0; i < 80; ++i)
{
producers[i] = std::thread(produce, ref(q));
}
std::thread consumers[100];
for (auto i = 0; i < 100; ++i)
{
consumers[i] = std::thread(consume, ref(q));
}
for (auto& producer : producers)
{
if (producer.joinable())
producer.join();
}
for (auto& consumer : consumers)
{
if (consumer.joinable())
consumer.join();
}
return 0;
}
四、线程池
|