IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++11新特性之多线程总结 -> 正文阅读

[C++知识库]c++11新特性之多线程总结

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');
        //std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void consume(std::shared_ptr<Queue>& q) {

    if (q == nullptr) {
        std::cout << "q is nullptr" << std::endl;
    }

    //std::this_thread::sleep_for(std::chrono::seconds(1));

    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();
        //std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

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;
}

四、线程池


  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-27 11:09:20  更:2022-04-27 11:10:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 23:27:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码