C++之线程同步之条件变量和互斥锁的使用

这篇文章主要说说线程同步的条件变量和互斥锁在线程中结合的使用,先看看几个概念
条件变量:是一种线程同步机制,条件变量允许线程睡眠,直到满足条件,当满足条件时,可以向该线程发信号,通知唤醒。
互斥锁: 互斥锁用于控制多个线程对他们之间共享资源互斥访问的一个信号量。也就是说是为了避免多个线程在某一时刻同时操作一个共享资源。

std::condition_variable 是为了解决死锁而生的。当互斥操作不够用而引入的。比如,线程可能需要等待某个条件为真才能继续执行,而一个忙等待循环中可能会导致所有其他线程都无法进入临界区使得条件为真时,就会发生死锁。所以,condition_variable实例被创建出现主要就是用于唤醒等待线程从而避免死锁。std::condition_variable的 notify_one()用于唤醒一个线程;notify_all() 则是通知所有线程。
C++11中的std::condition_variable就像Linux下使用pthread_cond_wait和pthread_cond_signal一样,可以让线程休眠,直到别唤醒,现在在从新执行。线程等待在多线程编程中使用非常频繁,经常需要等待一些异步执行的条件的返回结果。

为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起;通常情况下这个锁是std::mutex,并且管理这个锁 只能是 std::unique_lock<std::mutex> RAII模板类。

条件满足一般使用
等待条件成立使用的是condition_variable类成员wait 、wait_for 或 wait_until。给出信号使用的是condition_variable类成员notify_one或者notify_all函数

在条件变量中只能使用std::unique_lockstd::mutex说明

unique_lock和lock_guard都是管理锁的辅助类工具,都是RAII风格;它们是在定义时获得锁,在析构时释放锁。它们的主要区别在于unique_lock锁机制更加灵活,可以再需要的时候进行lock或者unlock调用,不非得是析构或者构造时。它们的区别可以通过成员函数就可以一目了然。

在线程被阻塞时,该函数会自动调用 lck.unlock() 释放锁,使得其他被阻塞在锁竞争上的线程得以继续执行。另外,一旦当前线程获得通知(notified,通常是另外某个线程调用 notify_* 唤醒了当前线程),wait() 函数也是自动调用 lck.lock(),使得 lck 的状态和 wait 函数被调用时相同。

//代码:
std::mutex m_utex;
std::queue<int> m_queue;
std::condition_variable m_cv;

BOOL bwhile = TRUE;
void thread_read2(CMFCApplication7Dlg *pDlg)
{
	while (bwhile)
	{
		std::unique_lock<std::mutex> m_lock(m_utex);
		
		m_cv.wait(m_lock, [](){return !m_queue.empty(); });
		if (bwhile == 0)
		{
			break;
		}

		int n = m_queue.front();
		m_queue.pop();
		m_lock.unlock();

		CString strTmp = _T("");
		strTmp.Format("thread_read2:%d", n);

		SetDlgItemText(pDlg->m_hWnd, IDC_EDIT1, strTmp);

		strTmp.Format("%d", m_queue.size());
		SetDlgItemText(pDlg->m_hWnd, IDC_EDIT2, strTmp);
		std::this_thread::sleep_for(std::chrono::milliseconds(1000));

	}
	return;
}
//开启读线程
void CMFCApplication7Dlg::OnBnClickedButton1()
{
	// TODO:  在此添加控件通知处理程序代码

	std::thread m_thread2(thread_read2, this);
	m_thread2.detach();

	GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);

}
//写数据
int icount = 1;
void CMFCApplication7Dlg::OnBnClickedButton2()
{
	// TODO:  在此添加控件通知处理程序代码
	m_queue.push(icount++);
	m_cv.notify_one();
}

结果:
在这里插入图片描述
在这里插入图片描述
下面这篇文章讲解的不错:
条件变量和互斥锁1
条件变量和互斥锁2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发如雪-ty

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值