当前位置: 首页 > article >正文

【C++ 面试 - 新特性】每日 3 题(九)

✍个人博客: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;
}

http://www.kler.cn/a/299170.html

相关文章:

  • 重拾设计模式--模板方法模式
  • Kubernetes(K8s)学习笔记
  • 关于如何做技术文档
  • Python:动态粒子爱心
  • 【自动驾驶】Ubuntu22.04源码安装Autoware Core/Universe
  • 笔记本重装系统教程【详细教程】
  • Ionic 头部和底部
  • 若依漏洞综合利用工具
  • 用于完善智能电表设计的 FPGA 到 ASIC 研究
  • 【C++二分查找 滑动窗口】2831. 找出最长等值子数组
  • hutool 集合相关交集、差集
  • A表和B表公共元素产生链表C
  • 各类软件在Linux上的安装
  • 多人开发小程序设置体验版的痛点
  • Vue知识点笔记(持续更新)
  • 使用 `readResolve` 防止序列化破坏单例模式
  • 【JVM】JVM栈帧中的动态链接 与 Java的面向对象特性--多态
  • 系统工程建模MBSE
  • 【STM32 Blue Pill编程】-定时器计数模式
  • 网络编程(学习)2024.9.5
  • WINDOWS下0-1编译ESP-AT
  • JAVA今日分享-30道常见的Java+MyBatis面试题
  • SQLite 与 Java 的集成
  • 鼠标点击来动态确定 HSV 范围
  • QT Creater实现国庆节主题项目【0基础完成版】
  • 算法工程师重生之第三天( 链表理论基础 移除链表元素 设计链表 反转链表 )