21xrx.com
2024-12-22 23:17:20 Sunday
登录
文章检索 我的文章 写文章
C++线程同步的三种方法
2023-07-02 17:01:47 深夜i     --     --
C++ 线程同步 三种方法

C++是一种面向对象的编程语言,常常用于开发大型应用程序和游戏等。在C++中,线程同步是一种非常重要的问题,尤其是在多线程编程中。线程同步的目的是保证多个线程之间的协调运行,从而避免出现竞争条件和死锁等问题。本文主要介绍C++中线程同步的三种方法。

1. 互斥锁

互斥锁是一种非常常见的线程同步方法。它的作用是保护临界区,确保同一时间只有一个线程可以访问共享资源。互斥锁可以通过C++标准库中的std::mutex类来实现。使用互斥锁的步骤通常包括:创建互斥锁,锁定互斥锁,访问共享资源,释放互斥锁。

示例代码:


#include <iostream>

#include <thread>

#include <mutex>

std::mutex mtx;

void print_thread_id(int id) {

  mtx.lock();

  std::cout << "thread id: " << id << '\n';

  mtx.unlock();

}

int main() {

  std::thread threads[10];

  for (int i = 0; i < 10; ++i) {

    threads[i] = std::thread(print_thread_id, i + 1);

  }

  for (auto& th : threads) {

    th.join();

  }

  return 0;

}

在上面的示例中,我们创建了10个线程,并使用互斥锁保护了对std::cout的访问。这样就可以确保每个线程输出时不会导致数据混乱。

2. 条件变量

条件变量是一种可以在多个线程之间传递信息的同步机制。它可以在共享资源达到某种条件时通知等待的线程。条件变量可以通过std::condition_variable类来实现。

示例代码:


#include <iostream>

#include <thread>

#include <mutex>

#include <condition_variable>

std::mutex mtx;

std::condition_variable cv;

bool ready = false;

void print_thread_id(int id) {

  std::unique_lock<std::mutex> lck(mtx);

  while (!ready) {

    cv.wait(lck);

  }

  std::cout << "thread id: " << id << '\n';

}

void start_thread() {

  std::this_thread::sleep_for(std::chrono::seconds(2));

  ready = true;

  cv.notify_all();

}

int main() {

  std::thread threads[10];

  for (int i = 0; i < 10; ++i) {

    threads[i] = std::thread(print_thread_id, i + 1);

  }

  std::thread start_thread(start_threads);

  start_thread.join();

  for (auto& th : threads) {

    th.join();

  }

  return 0;

}

在上面的示例中,我们创建了10个线程,并使用条件变量等待共享变量ready的状态变化。当共享变量ready被设置为true时,所有等待的线程都被唤醒。这样可以确保所有线程都可以在一起开始执行。

3. 原子操作

原子操作是一种可以确保操作的原子性的同步机制。它可以在多线程环境下进行不可中断的操作,从而避免竞争条件和死锁等问题。原子操作可以通过C++标准库中的std::atomic类来实现。

示例代码:


#include <iostream>

#include <thread>

#include <atomic>

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

void worker() {

  for (int i = 0; i < 1000000; ++i) {

    counter.fetch_add(1);

  }

}

int main() {

  std::thread threads[10];

  for (int i = 0; i < 10; ++i) {

    threads[i] = std::thread(worker);

  }

  for (auto& th : threads) {

    th.join();

  }

  std::cout << "counter: " << counter.load() << '\n';

  return 0;

}

在上面的示例中,我们使用原子操作实现了对共享变量counter的自增操作。这样可以确保多个线程同时对共享变量进行访问时不会发生数据竞争。

总结

本文介绍了C++中线程同步的三种常用方法:互斥锁、条件变量和原子操作。使用这些方法可以确保多线程程序的正确性和性能。在实际开发中,应该根据具体情况选择不同的同步方法,并注意避免竞争条件、死锁和饥饿等问题。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复