C++线程安全函数

devtools/2024/12/26 23:42:54/

在 C++ 中,线程安全的函数是指在多线程环境下可以安全调用,不会导致数据竞争或其他并发问题的函数。C++ 标准库提供了许多线程安全的函数,同时也要求开发者在使用自定义函数时确保线程安全。以下是一些常见的线程安全函数和实现线程安全的方法:


1. 标准库中的线程安全函数

C++ 标准库中的许多函数是线程安全的,尤其是那些不涉及共享状态的函数。

1.1 <iostream> 中的线程安全函数

  • std::cout 和 std::cerr
    • 这些对象是线程安全的,但输出可能会交错。
    • 如果需要保证输出顺序,可以使用互斥锁保护。

1.2 <atomic> 中的线程安全函数

  • std::atomic<T>
    • 所有操作(如 load()store()fetch_add() 等)都是原子的。
    • 示例:
      std::atomic<int> counter(0);
      counter++;  // 线程安全
      

1.3 <thread> 中的线程安全函数

  • std::thread::join()
    • 等待线程完成,线程安全的。
  • std::thread::detach()
    • 分离线程,线程安全的。

1.4 <mutex> 中的线程安全函数

  • std::mutex::lock() 和 std::mutex::unlock()
    • 用于保护共享资源,线程安全的。
  • std::lock_guard 和 std::unique_lock
    • 自动管理锁的生命周期,线程安全的。

1.5 <condition_variable> 中的线程安全函数

  • std::condition_variable::wait()
    • 等待条件变量,线程安全的。
  • std::condition_variable::notify_one() 和 notify_all()
    • 通知等待的线程,线程安全的。

1.6 <future> 中的线程安全函数

  • std::future::get()
    • 获取异步操作的结果,线程安全的。
  • std::promise::set_value()
    • 设置异步操作的结果,线程安全的。

1.7 <chrono> 中的线程安全函数

  • std::chrono::system_clock::now()
    • 获取当前时间,线程安全的。

2. 自定义线程安全函数

如果需要编写自定义的线程安全函数,可以通过以下方式实现:

2.1 使用互斥锁(std::mutex

通过互斥锁保护共享资源,确保线程安全。

示例:

#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;
int shared_data = 0;void threadSafeFunction() {std::lock_guard<std::mutex> lock(mtx);  // 自动加锁和解锁shared_data++;std::cout << "Shared data: " << shared_data << std::endl;
}int main() {std::thread t1(threadSafeFunction);std::thread t2(threadSafeFunction);t1.join();t2.join();return 0;
}

2.2 使用原子操作(std::atomic

对于简单的数据类型,可以使用原子操作避免数据竞争。

示例:

#include <iostream>
#include <thread>
#include <atomic>std::atomic<int> shared_data(0);void threadSafeFunction() {shared_data++;  // 原子操作std::cout << "Shared data: " << shared_data.load() << std::endl;
}int main() {std::thread t1(threadSafeFunction);std::thread t2(threadSafeFunction);t1.join();t2.join();return 0;
}

2.3 使用条件变量(std::condition_variable

通过条件变量实现线程间的同步。

示例:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
bool ready = false;void threadSafeFunction() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return ready; });  // 等待条件变量std::cout << "Thread is running." << std::endl;
}int main() {std::thread t(threadSafeFunction);{std::lock_guard<std::mutex> lock(mtx);ready = true;  // 修改条件}cv.notify_one();  // 通知等待的线程t.join();return 0;
}

3. 线程安全的容器

C++ 标准库提供了一些线程安全的容器,但需要注意的是,标准库容器本身并不是线程安全的,需要手动加锁保护。

3.1 线程安全的容器示例

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>std::mutex mtx;
std::vector<int> shared_vector;void threadSafeFunction(int value) {std::lock_guard<std::mutex> lock(mtx);  // 加锁保护shared_vector.push_back(value);
}int main() {std::thread t1(threadSafeFunction, 1);std::thread t2(threadSafeFunction, 2);t1.join();t2.join();for (int v : shared_vector) {std::cout << v << " ";}return 0;
}

4. 线程安全的单例模式

单例模式是一种常见的设计模式,可以通过双重检查锁定(Double-Checked Locking)实现线程安全的单例。

示例:

#include <iostream>
#include <mutex>
#include <memory>class Singleton {
public:static Singleton& getInstance() {static std::once_flag flag;std::call_once(flag, [] { instance.reset(new Singleton); });return *instance;}private:Singleton() = default;static std::unique_ptr<Singleton> instance;
};std::unique_ptr<Singleton> Singleton::instance;int main() {Singleton& s1 = Singleton::getInstance();Singleton& s2 = Singleton::getInstance();std::cout << &s1 << " " << &s2 << std::endl;  // 地址相同return 0;
}

总结

C++ 提供了丰富的工具来实现线程安全:

  1. 标准库函数:如 std::coutstd::atomicstd::mutex 等。
  2. 互斥锁:通过 std::mutex 保护共享资源。
  3. 原子操作:使用 std::atomic 避免数据竞争。
  4. 条件变量:通过 std::condition_variable 实现线程同步。
  5. 线程安全容器:手动加锁保护标准库容器。
  6. 单例模式:使用双重检查锁定或 std::call_once 实现线程安全的单例。

根据具体需求选择合适的方式,可以实现高效、安全的并发编程。

 


http://www.ppmy.cn/devtools/145655.html

相关文章

Vue3 核心语法

1. OptionsAPI 与 CompositionAPI Vue2 的API设计是 Options&#xff08;配置&#xff09;风格的。Vue3 的API设计是 Composition&#xff08;组合&#xff09;风格的。 1.1 Options API 的弊端 Options类型的 API&#xff0c;数据、方法、计算属性等&#xff0c;是分散在&a…

Qt Quick:ComboBox 组合框

自定义ComboBox&#xff1a; import QtQuick import QtQuick.Controls // import QtQuick.Controls.MaterialWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")ComboBox {id: comboBoxwidth: 150; height: 35; x: 50; y: 20model: ListModel {L…

安全筑堤,效率破浪 | 统一运维管理平台下的免密登录应用解析

在信息技术迅猛发展的今天&#xff0c;企业运维管理领域正面临着前所未有的复杂挑战。统一运维管理平台作为集中管理和监控IT基础设施的核心工具&#xff0c;其安全性和效率至关重要。免密登录作为一种新兴的身份验证技术&#xff0c;正逐渐成为提升运维管理效率和安全性的重要…

Pytorch | 利用VMI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用VMI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集VMI-FGSM介绍核心思想梯度方差定义算法流程 VMI-FGSM代码实现VMI-FGSM算法实现攻击效果 代码汇总vmifgsm.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器&#xff1a; Pytorch | 从零构…

oracle 加字段和字段注释 sql

在 Oracle 数据库中&#xff0c;你可以使用 ALTER TABLE 语句来添加字段&#xff0c;并使用 COMMENT ON COLUMN 语句来添加字段注释。以下是一个示例&#xff1a; 假设你有一个名为 employees 的表&#xff0c;你想要添加一个名为 email 的字段&#xff0c;并为其添加注释。 …

简单园区网拓扑实验

1.实验拓扑 2.实验要求 1、按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2、要求SW1为VLAN 2/3的主根及主网关 SW2为vlan 20/30的主根及主网关 SW1和SW2互为备份 3、可以使用super vlan 4、上层通过静态路由协议完成数据通信过程 5、AR1为企业出口路由器 6、要求全网可…

17_HTML5 Web 存储 --[HTML5 API 学习之旅]

HTML5 Web 存储&#xff08;Web Storage&#xff09;是 HTML5 引入的一种在用户浏览器中存储数据的机制。它提供了比传统的 cookies 更加方便和强大的功能&#xff0c;包括更大的存储空间、更好的性能以及更简单的 API。Web 存储主要分为两种类型&#xff1a;localStorage 和 s…

【童年经典小游戏】使用Python实现经典贪吃蛇游戏

文章目录 使用Python实现经典贪吃蛇游戏简介实现思路与准备游戏框架与库选择游戏基本逻辑 代码实现完整代码 代码关键点解析初始化与游戏窗口贪吃蛇的表示与移动食物的生成碰撞检测与游戏结束 运行代码中文不显示问题解决拓展与优化建议总结 使用Python实现经典贪吃蛇游戏 贪吃…