21xrx.com
2024-11-08 23:23:54 Friday
登录
文章检索 我的文章 写文章
如何在C++中实现多线程加锁
2023-06-29 22:13:32 深夜i     --     --
C++ 多线程 加锁 互斥锁 条件变量

在使用C++编写多线程应用程序时,常常需要使用锁来保护共享资源,以防止多个线程同时对资源进行访问而导致数据损坏或不一致。下面介绍一下如何在C++中实现多线程加锁。

1. 使用互斥锁

互斥锁是一种最常用的锁,它可以用来保护共享资源。在C++中,可以使用 std::mutex 类来创建一个互斥锁。当一个线程获取了锁之后,其他线程就需要等待该线程释放锁之后才能再次尝试获取锁。

下面是一个使用 std::mutex 的示例代码:


#include <iostream>

#include <thread>

#include <mutex>

std::mutex g_mutex;

void print(int n)

{

  g_mutex.lock();

  std::cout << "Thread " << n << " is running." << std::endl;

  g_mutex.unlock();

}

int main()

{

  std::thread t1(print, 1);

  std::thread t2(print, 2);

  std::thread t3(print, 3);

  t1.join();

  t2.join();

  t3.join();

  return 0;

}

在上面的示例代码中,创建了三个线程 t1、t2 和 t3,并共享了一个互斥锁 g_mutex。在 print 函数内,先调用了 g_mutex 的 lock 方法来获取锁,然后输出线程的编号,最后再调用 g_mutex 的 unlock 方法来释放锁。

2. 使用递归锁

递归锁是一种特殊的互斥锁,它允许同一个线程对同一个锁进行多次加锁操作。在C++中,可以使用 std::recursive_mutex 类来创建一个递归锁。当一个线程第一次获取锁之后,可以继续对该锁进行加锁操作,而其他线程需要等待该线程将所有的锁都释放之后才能尝试获取锁。

下面是一个使用 std::recursive_mutex 的示例代码:


#include <iostream>

#include <thread>

#include <mutex>

std::recursive_mutex g_mutex;

void print(int n)

{

  g_mutex.lock();

  g_mutex.lock();

  std::cout << "Thread " << n << " is running." << std::endl;

  g_mutex.unlock();

  g_mutex.unlock();

}

int main()

{

  std::thread t1(print, 1);

  std::thread t2(print, 2);

  std::thread t3(print, 3);

  t1.join();

  t2.join();

  t3.join();

  return 0;

}

在上面的示例代码中,创建了三个线程 t1、t2 和 t3,并共享了一个递归锁 g_mutex。在 print 函数内,先调用了 g_mutex 的 lock 方法两次来获取锁,然后输出线程的编号,最后再调用 g_mutex 的 unlock 方法两次来释放锁。

3. 使用条件变量

条件变量是一种特殊的锁,它可以用来控制线程的执行顺序。在C++中,可以使用 std::condition_variable 类来创建一个条件变量。当一个线程需要等待某个条件成立之后再继续执行时,可以调用该条件变量的 wait 方法来将自己挂起,直到其他线程唤醒它。

下面是一个使用 std::condition_variable 的示例代码:


#include <iostream>

#include <thread>

#include <mutex>

#include <condition_variable>

std::mutex g_mutex;

std::condition_variable g_cond;

bool g_ready = false;

void wait(int n)

{

  std::unique_lock<std::mutex> lock(g_mutex);

  while (!g_ready)

  {

    g_cond.wait(lock);

  }

  std::cout << "Thread " << n << " is running." << std::endl;

}

void signal()

{

  std::unique_lock<std::mutex> lock(g_mutex);

  g_ready = true;

  g_cond.notify_all();

}

int main()

{

  std::thread t1(wait, 1);

  std::thread t2(wait, 2);

  std::thread t3(wait, 3);

  std::this_thread::sleep_for(std::chrono::milliseconds(1000));

  signal();

  t1.join();

  t2.join();

  t3.join();

  return 0;

}

在上面的示例代码中,创建了三个线程 t1、t2 和 t3,并共享了一个互斥锁 g_mutex 和一个条件变量 g_cond。在 wait 函数内,先调用了 g_mutex 的 lock 方法来获取锁,然后调用 g_cond 的 wait 方法将自己挂起,直到其他线程调用了 signal 方法唤醒它。在 signal 函数内,先调用了 g_mutex 的 lock 方法来获取锁,然后设置 g_ready 为 true,最后调用 g_cond 的 notify_all 方法来唤醒所有等待的线程。在 main 函数内,先让程序休眠1秒钟,然后调用 signal 方法来唤醒等待的线程。最后调用 join 方法等待所有线程结束。

综上所述,互斥锁、递归锁和条件变量是C++中常用的多线程加锁机制。需要根据实际情况选择适当的锁机制来保护共享资源,以确保程序的正确性和可靠性。

  
  

评论区

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