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线程同步原语,以及使用场景。

C++11 线程同步原语有三个:mutex(互斥锁),condition variable(条件变量)和semaphore(信号量)。


一 mutex

mutex是最简单的同步原语,用来防止多个线程并发的访问临界区资源。如果应用中有些资源在同一时间最多只能被一个线程访问,那么就使用mutex来保护这些资源。

使用方法也非常简单,总共3步,

  1. 加锁
  2. 执行临界区代码
  3. 释放锁

下面是简单的范例代码,一般配合std::lock_guard或者std::unique_lock来使用

#include <iostream>
#include <map>
#include <string>
#include <chrono>
#include <thread>
#include <mutex>
 
std::map<std::string, std::string> g_pages;
std::mutex g_pages_mutex;
 
void save_page(const std::string &url)
{
    // simulate a long page fetch
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::string result = "fake content";
 
    std::lock_guard<std::mutex> guard(g_pages_mutex);
    g_pages[url] = result;
}
 
int main() 
{
    std::thread t1(save_page, "http://foo");
    std::thread t2(save_page, "http://bar");
    t1.join();
    t2.join();
 
    // safe to access g_pages without lock now, as the threads are joined
    for (const auto &pair : g_pages) {
        std::cout << pair.first << " => " << pair.second << '\n';
    }
    return 0;
}

加锁由guard的构造函数来完成,释放锁由guard的析构函数来完成,只要出了guard的作用域就会自动释放。

PS: std::mutex提供的互斥锁是non-recursive的


二 condition variable

条件变量用于实现多个线程间的notification/synchronization机制,使用场景如下,

Condition variable allows a thread T to wait for completion of a given event on a particular object (some shared state, data structure, anything). The event over here is really the change in state of some condition that thread is interested in. Until that is satisfied, the thread waits to be awakened later by a signalling thread (that actually changes the condition).

这个notification/synchronization机制是mutex无法做到的。

条件变量的使用需要3个元素,

  1. 条件变量 (同步原语)
  2. 互斥锁
  3. 条件 (一个共享变量或其它)

下面是个简单范例,代码中cv是条件变量,m是互斥锁,ready和processed是条件

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
 
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
 
void worker_thread()
{
    // Wait until main() sends data
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{return ready;});
 
    // after the wait, we own the lock.
    std::cout << "Worker thread is processing data\n";
    data += " after processing";
 
    // Send data back to main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";
 
    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    cv.notify_one();
}
 
int main()
{
    std::thread worker(worker_thread);
 
    data = "Example data";
    // send data to the worker thread
    {
        std::lock_guard<std::mutex> lk(m);
        ready = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();
 	
    // wait for the worker
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
    std::cout << "Back in main(), data = " << data << '\n';
 
    worker.join();
    return 0;
}

运行逻辑如下,

  1. worker_thread调用cv.wait()时,条件ready是false,就会释放互斥锁,然后在那里等待通知
  2. 主线程先去拿锁,然后把条件ready修改为true,接着释放锁,最后通知worker_thread
  3. worker_thread接到通知后发现条件为真,又会获取锁,接着处理data,并把条件processed置位true
  4. 同理可以分析条件processed

三 semaphore

信号量提供了以下2个特性:

  1. 允许N个线程并发访问临界区,N与应用相关
  2. 提供了类似条件变量的notification/synchronization机制

本人没有使用过信号量…

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-04 11:00:48  更:2021-08-04 11:03:24 
 
开发: 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/9 14:21:22-

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