个人博客:Pandaconda-CSDN博客
专栏地址:http://t.csdnimg.cn/fYaBd
专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~
️如果有收获的话,欢迎点赞收藏,您的支持就是我创作的最大动力

25. 线程间同步通信 - 生产者消费者模型

两者生产一个就消费一个,结束后互相通知对方。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue> //STL所有容器都不是线程安全

using namespace std;

std::mutex mtx; //定义互斥锁, 线程间互斥
std::condition_variable cv; //定义条件变量, 线程间通信

class Queue
{
public:
    void put(int val)
    {
        //lock_guard<std::mutex>guard(mtx);//error scoped_ptr 左值拷贝构造和赋值都delete了
        unique_lock<std::mutex> lck(mtx); //防止这把锁被释放了
        while (!que.empty())
        {
            cv.wait(lck); //线程进入等待, 并把mtx锁释放
        }
        que.push(val);
        cv.notify_all(); //其他线程得到该通知,从等待变为阻塞,获取锁后继续执行
        cout << "生产者 生产:" << val << " 号物品" << endl;
    }
    int get()
    {
        //lock_guard<std::mutex>guard(mtx);
        unique_lock<std::mutex>lck(mtx);
        while (que.empty())
        {
            cv.wait(lck);
        }
        int val = que.front();
        que.pop();
        cv.notify_all();
        cout << "消费者 消费:" << val << "号物品" << endl;
        return val;
    }
private:
    queue<int> que;
};

void producer(Queue* que)
{
    for (int i = 0; i < 10; i++)
    {
        que->put(i);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void consumer(Queue* que)
{
    for (int i = 0; i < 10; i++)
    {
        que->get();
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

int main()
{
    Queue que;

    std::thread t1(producer, &que);
    std::thread t2(consumer, &que);

    t1.join();
    t2.join();

    return 0;
}

26. 再谈 lock_guard 和 unique_lock

lock_guard 和 unique_lock

  • unique_lock:不仅可以使用在简单的临界区代码段的互斥操作中,还能用在函数调用过程中。
  • lock_guard:不可能用在函数参数传递或者返回过程中,只能用在简单的临界区代码段的互斥操作中。
    condition_variable wait 和 notify_all 方法
  • notify_all:通知在 cv 上等待的线程,条件成立了,起来干活。其它 cv 上等待的线程收到通知,从等待态到阻塞态。

27. 基于 CAS 操作的 atomic 原子类型

互斥锁比较重,效率比较低,临界区代码做的事情稍稍复杂时再用。
用 CAS 来保证 ++ – 操作的原子特性就足够了(无锁操作)。

无锁队列:

#include <iostream>
#include <mutex>
#include <condition_variable>
#include <atomic> //包含了很多原子类型
#include <list>

using namespace std;

//volatile 防止多线程对共享变量进行缓存
volatile std::atomic_bool isReady = true; 
volatile std::atomic_int ccount = 0;
//int ccount = 0;

void task()
{
    while (!isReady)
    {
        std::this_thread::yield(); //线程出让当前的cpu时间片,等待下一次调度
    }
    for (int i = 0; i < 1000; i++)
        ccount++;
}

int main()
{
    list<std::thread> tlist;
    for (int i = 0; i < 10; i++) {
        tlist.push_back(std::thread(task));
    }
    for (auto& t : tlist)
    {
        t.join();
    }
    cout << ccount << endl;
    return 0;
}

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部