C++线程安全函数

发布于:2025-02-11 ⋅ 阅读:(104) ⋅ 点赞:(0)

在 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 实现线程安全的单例。

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

 


网站公告

今日签到

点亮在社区的每一天
去签到