C++ 并发编程(二):Mutex(互斥锁)

发布时间:2019-06-15 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了C++ 并发编程(二):Mutex(互斥锁)脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

多个线程访问同一资时,为了保证数据的一致性,最简单的方式就是使用 mutex(互斥锁)。

引用 cpPReference 的介绍:

The mutex class is a synchronization primITive that can be used to protect shared data From being simultaneously accessed by multiple threads.

Mutex 1

直接操作 mutex,即直接调用 mutex 的 lock / unlock 函数。

#include <iostream>
#include <;mutex>
#include <thread>
#include <vector>


std::mutex g_mutex;
int g_count = 0;

void Counter() {
  g_mutex.lock();

  int i = ++g_count;
  std::cout << "count: " << i << std::endl;

  // 前面代码如有异常,unlock 就调不到了。
  g_mutex.unlock();
}

int main() {
  const std::size_t SIZE = 4;

  // 创建一组线程。
  std::vector<std::thread> v;
  v.reserve(SIZE);

  for (std::size_t i = 0; i < SIZE; ++i) {
    v.emplace_back(&amp;Counter);
  }

  // 等待所有线程结束。
  for (std::thread& t : v) {
    t.join();
  }

  return 0;
}

可惜的是,STL 没有提供 boost::thread_group 这样代表一组线程的工具,通过 std::vector 固然也能达到目的,但是代码不够简洁。

Mutex 2

使用 lock_Guard 自动加锁、解锁。原理是 RAII,和智能指针类似。

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

std::mutex g_mutex;
int g_count = 0;

void Counter() {
  // lock_guard 在构造函数里加锁,在析构函数里解锁。
  std::lock_guard<std::mutex> lock(g_mutex);

  int i = ++g_count;
  std::cout << "count: " << i << std::endl;
}

int main() {
  const std::size_t SIZE = 4;

  std::vector<std::thread> v;
  v.reserve(SIZE);

  for (std::size_t i = 0; i < SIZE; ++i) {
    v.emplace_back(&Counter);
  }

  for (std::thread& t : v) {
    t.join();
  }

  return 0;
}

Mutex 3

使用 unique_lock 自动加锁、解锁。
unique_locklock_guard 原理相同,但是提供了更多功能(比如可以结合条件变量使用)。
注意:mutex::scoped_lock 其实就是 unique_lock<mutex>typedef

至于 unique_locklock_guard 详细比较,可移步 StackOverflow

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

std::mutex g_mutex;
int g_count = 0;

void Counter() {
  std::unique_lock<std::mutex> lock(g_mutex);

  int i = ++g_count;
  std::cout << "count: " << i << std::endl;
}

int main() {
  const std::size_t SIZE = 4;

  std::vector<std::thread> v;
  v.reserve(SIZE);

  for (std::size_t i = 0; i < SIZE; ++i) {
    v.emplace_back(&Counter);
  }

  for (std::thread& t : v) {
    t.join();
  }

  return 0;
}

Mutex 4

为输出流使用单独的 mutex。
这么做是因为 IO 流并不是线程安全的!
如果不对 IO 进行同步,此例的输出很可能变成:

count == count == 2count == 41
count == 3

因为在下面这条输出语句中:

std::cout << "count == " << i << std::endl;

输出 "count == " 和 i 这两个动作不是原子性的(atomic),可能被其他线程打断。

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

std::mutex g_mutex;
std::mutex g_io_mutex;
int g_count = 0;

void Counter() {
  int i;
  {
    std::unique_lock<std::mutex> lock(g_mutex);
    i = ++g_count;
  }

  {
    std::unique_lock<std::mutex> lock(g_io_mutex);
    std::cout << "count: " << i << std::endl;
  }
}

int main() {
  const std::size_t SIZE = 4;

  std::vector<std::thread> v;
  v.reserve(SIZE);

  for (std::size_t i = 0; i < SIZE; ++i) {
    v.emplace_back(&Counter);
  }

  for (std::thread& t : v) {
    t.join();
  }

  return 0;
}

脚本宝典总结

以上是脚本宝典为你收集整理的C++ 并发编程(二):Mutex(互斥锁)全部内容,希望文章能够帮你解决C++ 并发编程(二):Mutex(互斥锁)所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。