21xrx.com
2024-12-22 21:24:02 Sunday
登录
文章检索 我的文章 写文章
C++线程之间的通信方法介绍
2023-07-04 06:55:05 深夜i     --     --
C++ 线程 通信方法 互斥锁 条件变量

C++是一种常见的编程语言,在多线程编程中使用广泛。在多线程程序中,不同的线程需要相互通信。线程之间的通信是多线程编程中必不可少的一部分,可以实现数据共享和协作。本文将会介绍C++线程之间的通信方法。

1. 互斥锁

互斥锁是最常用的线程通信方法之一。当多个线程尝试同时访问共享资源时,可能会导致数据竞争和不一致。互斥锁可以确保在同一时刻只有一个线程能够访问共享资源。

C++标准库提供了std::mutex类来实现互斥锁。下面的代码演示了如何使用互斥锁通信:


#include <iostream>

#include <thread>

#include <mutex>

std::mutex mtx; // 创建互斥锁

void threadFunc(int &val)

{

 // 加锁互斥锁

 mtx.lock(); 

 std::cout << "Thread " << std::this_thread::get_id() << " incrementing value" << std::endl;

 ++val;

 // 解锁互斥锁

 mtx.unlock();

}

int main()

{

 int val = 0;

 std::thread t1(threadFunc, std::ref(val));

 std::thread t2(threadFunc, std::ref(val));

 t1.join();

 t2.join();

 std::cout << "Final value: " << val << std::endl;

 return 0;

}

在上面的例子中,我们创建了一个互斥锁来保护共享变量val。在每个线程中,加锁互斥锁,访问共享变量,然后解锁互斥锁。这样我们就能够确保在同一时刻只有一个线程能够访问共享变量val,避免竞争条件。

2. 条件变量

条件变量用于线程之间的同步,它们允许线程等待某个条件的发生。条件变量通常与互斥锁一起使用,以确保在线程等待时不会出现竞争条件。

C++标准库提供了std::condition_variable类来实现条件变量。下面是一个使用条件变量通信的例子:


#include <iostream>

#include <thread>

#include <mutex>

#include <condition_variable>

std::mutex mtx;

std::condition_variable cv;

bool isReady = false;

void threadFunc()

{

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

 std::cout << "Waiting for isReady flag" << std::endl;

 cv.wait(lock, []{return isReady;});

 std::cout << "isReady flag set, do some other work" << std::endl;

}

int main()

{

 std::thread t1(threadFunc);

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

 isReady = true;

 cv.notify_one();

 t1.join();

 return 0;

}

在上面的例子中,我们创建了一个条件变量cv和一个bool变量isReady。在主线程中,我们等待1秒钟,然后将isReady设置为true,并通过调用cv.notify_one()通知等待中的线程。在线程函数中,我们首先加锁互斥锁,然后调用cv.wait()等待isReady为true。当isReady被设置为true时,线程将被唤醒并继续执行。

3. 信号量

信号量是一种能够在多线程之间同步访问共享资源的基本方式。它是一种计数器,用于控制对共享资源的访问。信号量的值可以增加或减少。当一个线程访问共享资源时,它将尝试获取信号量。如果信号量的值为0,线程将被阻塞,直到信号量的值变为非零。当线程完成对共享资源的访问并释放资源时,它将增加信号量的值。

C++标准库没有提供信号量的实现,但是可以使用第三方库的信号量实现。下面是使用POSIX信号量库的示例:


#include <iostream>

#include <thread>

#include <semaphore.h>

sem_t sem;

void threadFunc()

{

 std::cout << "Thread " << std::this_thread::get_id() << " waiting for semaphore" << std::endl;

 sem_wait(&sem);

 std::cout << "Thread " << std::this_thread::get_id() << " acquired semaphore, do some work" << std::endl;

 sem_post(&sem);

}

int main()

{

 sem_init(&sem, 0, 1);

 std::thread t1(threadFunc);

 std::thread t2(threadFunc);

 t1.join();

 t2.join();

 sem_destroy(&sem);

 return 0;

}

在上面的例子中,我们通过调用sem_init()函数初始化一个信号量sem,其初始值为1。在线程函数中,我们调用sem_wait()等待信号量,然后调用sem_post()释放信号量。在主函数中,我们创建了两个线程来同时访问信号量。当一个线程正在访问共享资源时,另一个线程将被阻塞,直到信号量的值变为1。

通过上述介绍,我们了解了C++线程之间的三种通信方法:互斥锁、条件变量和信号量。不同的场景和需求可以选择不同的通信方法,以实现可靠的多线程应用。

  
  

评论区

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