C++多线程中互斥锁与条件变量的详解与实战

Jasper
Jasper
发布时间:2026-10-16| 4人浏览过
原创

在C++并发编程中,互斥锁(std::mutex)用于保护共享资源避免竞态条件,而条件变量(std::condition_variable)则允许线程在特定条件下休眠并等待唤醒,从而实现复杂的线程协作。本文将通过实际代码演示这两者的实现原理与应用。

1. 为什么需要线程同步机制

在多线程环境中,多个线程可能会同时访问同一个全局变量或对象,这会导致不可预知的结果。例如:

初始代码示例:

int g_num = 0;
void print(int id)
{
	for (int i = 0; i < 5; i++)
	{
		++g_num;
		cout << "id = " << id << "==>|" << g_num << endl;
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
}
int main()
{
	thread tha(print, 0);
	thread thb(print, 1);
	tha.join();
	thb.join();
	return 0;
}

运行结果显示输出混乱且数值不正确,原因在于 --> 运算不是原子操作。为解决此问题,可先尝试使用原子类型:

atomic_int g_num = 0; //或者 std::atomic<int> g_num = 0;
void print(int id)
{
	for (int i = 0; i < 5; i++)
	{
		++g_num;
		cout << "id = " << id << "==>" << g_num << endl;
		std::this_thread::sleep_for(std::chrono::microseconds(500));
	}
}
int main()
{
	thread tha(print, 0);
	thread thb(print, 1);
	tha.join();
	thb.join();
	return 0;
}

改为原子操作后虽然数据完整性得到保证,但打印结果依然可能出现乱序(如连打两个4、两个6)。接下来引入互斥锁(Mutex)来严格保护关键区域。

第1步:使用互斥锁进行基本同步

目的:确保在同一时刻只有一个线程能够修改共享资源。

int g_num = 0;
std::mutex mtx;  // 创建锁对象
void print(int id)
{
	for (int i = 0; i < 5; i++)
	{
		mtx.lock();  // 上锁
		++g_num;
		cout << "id = " << id << "==>" << g_num << endl;
		mtx.unlock(); // 解锁
		std::this_thread::sleep_for(std::chrono::microseconds(500));
	}
}
int main()
{
	thread tha(print, 0);
	thread thb(print, 1);
	tha.join();
	thb.join();
	return 0;
}

官方文档显示 std::mutex 构造函数是唯一的公开接口,拷贝构造被删除,因此它不能被复制传递。

第2步:使用 try_lock 提高灵活性

try_lock() 尝试获取锁,如果成功返回 true,失败则立即返回 false 而不阻塞当前线程。但如果未加循环判断直接使用,可能会导致解锁未上锁的互斥锁从而引发异常。

错误示范(无循环):

int g_num = 0;
std::mutex mtx;
void print(int id)
{
	for (int i = 0; i < 5; i++)
	{
		mtx.try_lock();  
		++g_num;
		cout << "id = " << id << "==>" << g_num << endl;
		mtx.unlock();
		std::this_thread::sleep_for(std::chrono::microseconds(500));
	}
}

正确示范(配合 while 循环):

int g_num = 0;
std::mutex mtx;
void print(int id)
{
	for (int i = 0; i < 5; i++)
	{
		while (!mtx.try_lock()) 
		{
			cout << "try lock" << endl;
		}    
		++g_num;
		cout << "id = " << id << "==>" << g_num << endl;
		mtx.unlock();
		std::this_thread::sleep_for(std::chrono::microseconds(500));
	}
}

该方法虽有效,但频繁轮询会消耗大量 CPU 资源。

2. 进阶:结合互斥锁与条件变量实现多线程顺序协作

当我们需要让多个线程按特定顺序交替执行时(如 A 打印后 B 打印,B 打印后 C 打印),单纯靠互斥锁难以控制,此时需引入 std::condition_variable。

以下示例实现了三个线程交替打印字符 'A', 'B', 'C' 共 100 次:


std::mutex mtx;
std::condition_variable cv;
int isReady = 0;
const int n = 100;

void print_A() {
	std::unique_lock<mutex> lock(mtx);
	int i = 0;
	while (i < n) {
		while (isReady != 0) 
			cv.wait(lock);
		cout << "A" ;
		isReady = 1;
		++i;
		std::this_thread::sleep_for(std::chrono::microseconds(100));
		cv.notify_all(); 
	}
}

void print_B() {
	std::unique_lock<mutex> lock(mtx);
	int i = 0;
	while (i < n) {
		while (isReady != 1)
			cv.wait(lock);
		cout << "B" ;
		isReady = 2;
		++i;
		std::this_thread::sleep_for(std::chrono::microseconds(100));
		cv.notify_all();
	}
}

void print_C() {
	std::unique_lock<mutex> lock(mtx);
	int i = 0;
	while (i < n) {
		while (isReady != 2)
			cv.wait(lock);
		cout << "C" ;
		isReady = 0;
		++i;
		std::this_thread::sleep_for(std::chrono::microseconds(100));
		cv.notify_all();
	}
}
int main() {
	thread tha(print_A);
	thread thb(print_B);
	thread thc(print_C);
	tha.join();
	thb.join();
	thc.join();
	return 0;
}

运行结果分析

在上述代码中,cv.notify_all() 用于唤醒所有因 cv.wait(lock) 阻塞的线程。配合状态变量 isReady,各个线程检查自身状态决定是否继续运行。若改用 notify_one(),系统只会随机唤醒一个等待中的线程,可能导致死锁或长时间挂起。

3. 总结

互斥锁解决了多线程对共享资源的竞争问题,保证了数据的完整性;条件变量则提供了高效的线程通知与等待机制,使得编写复杂的多线程协作逻辑成为可能。两者结合是构建高性能并行应用的基础手段。

以上就是C++多线程互斥锁和条件变量的详细内容,更多关于C++并发编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。