21xrx.com
2024-06-03 06:01:56 Monday
登录
文章检索 我的文章 写文章
C++11多线程经典案例
2023-07-11 15:27:23 深夜i     --     --
C++11 多线程 经典案例

随着计算机性能的不断提高和多核处理器的普及,多线程编程已经成为了现代软件开发的重要组成部分。然而,在多线程编程中,由于线程的并发执行和共享资源的访问,程序的正确性和性能一直是难题。为了解决这个问题,C++11引入了一系列的语言特性和库函数,为多线程编程提供了更加便捷和安全的方式。

在本文中,我们将介绍几个C++11多线程经典案例。

1. 线程同步

在多线程编程中,线程之间共享的变量和资源可能会引发竞争条件,从而导致程序出错。为了避免这种问题,我们需要使用线程同步机制来协调线程之间的计算和数据访问。

C++11提供了一个std::mutex类来实现线程互斥。我们可以使用std::lock_guard类来自动管理mutex的锁定和解锁操作,从而避免手动实现锁操作的复杂性。

例如,下面的代码演示了如何使用std::mutex和std::lock_guard来保护数据结构的读写:


#include <mutex>

#include <vector>

std::vector<int> data; // 共享数据

void add_data(int n) {

  static std::mutex mtx; // 只在第一次调用时初始化

  std::lock_guard<std::mutex> lock(mtx); // 锁定互斥量

  data.push_back(n); // 执行写操作

}

int get_data(int index) {

  static std::mutex mtx; // 只在第一次调用时初始化

  std::lock_guard<std::mutex> lock(mtx); // 锁定互斥量

  return data[index]; // 执行读操作

}

2. 原子操作

除了互斥锁之外,C++11还引入了原子类型和原子操作来保证共享变量的原子性。原子操作是一种对共享变量进行操作的原子性语句,可以保证不会发生竞争条件,从而避免了锁定互斥量的开销和死锁的问题。

C++11提供了多种原子类型和原子操作,包括std::atomic、std::atomic_flag、std::atomic_exchange等。下面是一个使用std::atomic进行原子操作的例子:


#include <atomic>

std::atomic<int> counter(0); // 原子计数器

void inc_counter() {

  counter.fetch_add(1); // 原子递增

}

int get_counter() {

  return counter.load(); // 原子读取

}

3. 条件变量

在多线程编程中,我们经常需要等待某个条件达成,然后再继续执行。C++11提供了std::condition_variable类来实现这个功能。条件变量可以让线程在等待时进入睡眠状态,并在条件满足时自动唤醒,从而避免了占用CPU资源的问题。

例如,下面的代码演示了如何使用std::condition_variable和std::unique_lock来等待线程条件达成:


#include <condition_variable>

#include <mutex>

std::mutex mtx; // 互斥量

std::condition_variable cv; // 条件变量

bool ready = false;

void wait_for_ready() {

  std::unique_lock<std::mutex> lock(mtx); // 锁定互斥量

  while (!ready) {

    cv.wait(lock); // 等待条件变量

  }

  // 条件满足,执行操作

}

void set_ready() {

  std::unique_lock<std::mutex> lock(mtx); // 锁定互斥量

  ready = true; // 设置条件

  cv.notify_all(); // 唤醒所有等待线程

}

4. 异步操作

异步操作是一种并行编程模式,可以将计算任务分离成多个独立的部分,并在多个线程上同时执行,从而提高程序的性能和响应时间。

C++11提供了std::async函数和std::future类来实现异步操作。std::async函数可以在后台启动一个线程,并返回一个std::future对象,用于检查操作的状态和获取返回值。

下面是一个使用std::async和std::future进行异步操作的例子:


#include <future>

int do_work()

  // 执行计算任务

  return 42;

void process_async() {

  std::future<int> fut = std::async(do_work); // 异步执行计算任务

  int result = fut.get(); // 等待计算任务完成并获取返回值

  // 处理返回值

}

在本文中,我们介绍了几个C++11多线程的经典案例,包括线程同步、原子操作、条件变量和异步操作。这些技术可以提高多线程程序的正确性和性能,是现代软件开发的重要组成部分。

  
  

评论区

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