专业编程基础技术教程

网站首页 > 基础教程 正文

C++开发:解决多线程对共享资源的访问,同步原语使用

ccvgpt 2024-11-11 11:24:06 基础教程 8 ℃

C++ 提供了多种线程同步原语来帮助开发者在多线程环境中协调线程的执行。这些同步原语主要包括以下几类:

1. 互斥锁(Mutex)

互斥锁用于保护共享资源,确保同一时间只有一个线程可以访问该资源。

C++开发:解决多线程对共享资源的访问,同步原语使用

  • std::mutex:标准的互斥锁。
  • std::timed_mutex:支持定时的互斥锁。
  • std::recursive_mutex:允许同一线程多次锁定的递归互斥锁。
  • std::recursive_timed_mutex:支持定时的递归互斥锁。

示例

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx);
    ++counter;
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);

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

    std::cout << "Counter: " << counter << std::endl;
    return 0;
}

2. 条件变量(Condition Variable)

条件变量用于线程间的等待和通知机制,配合互斥锁使用。

  • std::condition_variable
  • std::condition_variable_any

示例

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id(int id) {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; });
    std::cout << "Thread " << id << std::endl;
}

void go() {
    std::lock_guard<std::mutex> lock(mtx);
    ready = true;
    cv.notify_all();
}

int main() {
    std::thread threads[10];
    for (int i = 0; i < 10; ++i)
        threads[i] = std::thread(print_id, i);

    std::cout << "10 threads ready to race...\n";
    std::this_thread::sleep_for(std::chrono::seconds(1));
    go();

    for (auto& th : threads) th.join();

    return 0;
}

3. 原子操作(Atomic Operations)

原子操作是无锁的同步机制,适用于简单的读写操作。

  • std::atomic:模板类,用于定义原子变量。
  • std::atomic_flag:最简单的原子类型,只支持两种状态(设置和清除)。

示例

#include <iostream>
#include <thread>
#include <atomic>

std::atomic<int> counter(0);

void increment() {
    for (int i = 0; i < 1000; ++i) {
        counter.fetch_add(1, std::memory_order_relaxed);
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);

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

    std::cout << "Counter: " << counter.load(std::memory_order_relaxed) << std::endl;
    return 0;
}

4. 读写锁(Reader-Writer Lock)

读写锁允许多个线程同时读取,但写操作是独占的。

  • std::shared_mutex(C++17 引入)
  • std::shared_timed_mutex

示例

#include <iostream>
#include <thread>
#include <shared_mutex>

std::shared_mutex mtx;
int counter = 0;

void reader() {
    std::shared_lock<std::shared_mutex> lock(mtx);
    std::cout << "Counter: " << counter << std::endl;
}

void writer() {
    std::unique_lock<std::shared_mutex> lock(mtx);
    ++counter;
}

int main() {
    std::thread t1(reader);
    std::thread t2(writer);
    std::thread t3(reader);

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

    return 0;
}

5. 其他同步原语

  • std::future 和 std::promise:用于线程间的值传递和同步。
  • std::packaged_task:将函数包装成异步任务。
  • std::latch(C++20 引入):用于线程间的计数同步。
  • std::barrier(C++20 引入):用于线程间的阶段性同步。

Future 和 Promise 示例

#include <iostream>
#include <thread>
#include <future>

int calculate(int x) {
    return x * 2;
}

int main() {
    std::promise<int> promise;
    std::future<int> future = promise.get_future();

    std::thread t([&promise]() {
        promise.set_value(calculate(10));
    });

    std::cout << "Result: " << future.get() << std::endl;

    t.join();
    return 0;
}

这些同步原语为开发者提供了丰富的工具来处理多线程环境中的各种同步需求。选择合适的同步原语可以提高程序的性能和正确性。

最近发表
标签列表