c++多线程(九) - condition_variable & wait() & notify_one()

    条件变量(condition_variable)是一个和条件相关的类,通常和互斥量配合使用。

    本文主要介绍条件变量的两个函数wait() 和notify_one()。

1.wait()和notify_one()

    wait() 阻塞程序,等待条件的达成。notify_one() 把被阻塞在wait()的线程唤醒。

    在库函数中,函数wait有两个重载。

void wait(unique_lock<mutex>& _Lck)
{	// wait for signal
    _Cnd_waitX(_Mycnd(), _Lck.mutex()->_Mymtx());
}

template<class _Predicate>
void wait(unique_lock<mutex>& _Lck, _Predicate _Pred)
{	// wait for signal and test predicate
    while (!_Pred())
        wait(_Lck);
}

    函数有两个参数,程序执行到wait()语句时:

    (1).对互斥量加锁。

    (2).执行第二个参数表示的函数 _Pred。

    (3).函数 _Pred 返回false时,对互斥量解锁,程序阻塞,等待其它线程调用nofify_one()将其唤醒后,回到步骤(1)。

    (4).函数 _Pred返回true时,程序继续执行。

    函数只有一个参数,程序执行到wait()语句时阻塞(相当于第二参数表示的函数始终返回false),等待其它线程调用nofify_one()将其唤醒后,再继续执行(相当于第二参数表示的函数始终返回true)。

2. 代码实例

#include<iostream>
#include<thread>
#include<mutex>
#include<list>
using namespace std;

class MsgManage
{
public:
	MsgManage() {}
	~MsgManage() {}
	void InMsg()
	{
		for (int i = 0; i < 10000; i++)
		{
			cout << "插入元素: " << i << endl;
			std::unique_lock<std::mutex> guard(myMutex);
			myList.push_back(i);
			//把被阻塞在wait()的线程唤醒
			condition.notify_one();
		}
	}
	
	void OutMsg()
	{
		int num;
		while (true)
		{
			std::unique_lock<std::mutex> guard(myMutex);
			//列表为空时,对互斥量解锁,程序阻塞,等待被唤醒。
			//列表不为空时,程序继续执行。
			condition.wait(guard, [this] {
				if (!myList.empty())
					return true;
				return false;
			});
			//程序执行到这里,列表不为空,且互斥量已被加锁
			num = myList.front();
			myList.pop_front();
			//解锁,避免互斥量被锁住太长时间
			guard.unlock(); 
			cout << "移除元素: " << num << endl;

			//程序继续执行其它耗时代码
		}		
	}
private:
	list<int> myList;
	mutex myMutex;
	condition_variable condition;  //条件变量对象和互斥量配合使用
};

int main()
{
	MsgManage manage;
	thread outMsg(&MsgManage::OutMsg, &manage);
	thread inMsg(&MsgManage::InMsg, &manage);
	inMsg.join();
	outMsg.join();
	return 0;
}

3. 存在问题

    上述代码很好的演示了程序的阻塞和唤醒,减少了很多无意义的条件判断。但是依然存在一些问题。

    (1)  执行notify_one() 时,如果没有线程阻塞在wati()时,此次唤醒就没有实际效果。

  (2)当函数InMsg()执行完10000次循环后,不再会执行notify_one(),此时很可能有线程阻塞在wait()上,永远不会被唤醒了。

    对于此问题,后续的文章中会做进一步改进。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: notify_one() 是 condition_variable 类的一个成员函数,它的作用是唤醒一个正在等待 condition_variable 的线程,使其获得锁并继续执行。它只会唤醒一个等待的线程,所以如果有多个线程在等待,那么只有一个线程会被唤醒,其他线程还是处于等待状态。使用 notify_one() 的方法是:在线程中使用 std::unique_lock 对象来锁定 condition_variable,然后调用 condition_variablewait() 方法来等待,当线程需要唤醒其他线程时,调用 notify_one() 来唤醒等待的线程。 ### 回答2: condition_variable中的notify_one()函数是C++标准库中用于通知等待在特定条件的线程的函数。当某个线程处于wait状态且在condition_variable上等待时,调用notify_one()函数可以唤醒其中的一个线程,使其继续执行。 notify_one()函数的用法较为简单,只需在需要唤醒线程的地方调用该函数即可。当有线程调用condition_variablewait()函数等待时,其他线程可以通过调用notify_one()函数来唤醒其中一个等待的线程。 需要注意的是,notify_one()函数并不会立即唤醒等待的线程,而是将其加入到就绪队列中,等待系统调度。因此不能确定哪个线程会被唤醒,也不能保证唤醒的顺序。如果需要唤醒多个线程,可以使用condition_variablenotify_all()函数。 notify_one()函数通常与unique_lock结合使用。在调用notify_one()之前,需要先获得与condition_variable关联的互斥锁,并在互斥锁的作用域内进行唤醒操作,以确保线程安全。 总的来说,condition_variable中的notify_one()函数是一种线程同步的机制,通过唤醒等待的线程来实现线程之间的协作。可以用于多线程之间的通信,提高程序的灵活性和效率。 ### 回答3: condition_variable 中的 notify_one() 是一个函数,用于通知等待在条件变量上的线程中的一个线程醒来。如果没有正在等待的线程,该函数不会做任何操作。该函数在多线程编程中被用于线程间的同步与协调。 通常情况下,notify_one() 函数应该和 unique_lock 结合使用。 unique_lock 是一个互斥锁的包装类,它提供了更灵活的锁定和解锁操作,可以在需要的时候进行线程阻塞或者唤醒操作。 notify_one() 的用法如下: 1. 创建一个条件变量对象和一个互斥锁对象。 2. 创建线程函数,并在该函数内部获取互斥锁。在获取锁之前,线程会等待条件变量上的 notify_one() 函数的通知。 3. 创建主线程,并在主线程内部调用 notify_one(),来通知等待在条件变量上的线程中的一个线程醒来。 4. 主线程调用 join() 函数,等待所有线程执行完毕。 5. 主线程释放互斥锁。 下面是一个简单的示例代码: ```cpp #include <iostream> #include <thread> #include <mutex> #include <condition_variable> std::mutex mtx; std::condition_variable cv; bool ready = false; void worker_thread() { std::unique_lock<std::mutex> lock(mtx); std::cout << "Worker thread is waiting..." << std::endl; cv.wait(lock, [] { return ready; }); std::cout << "Worker thread is awakened." << std::endl; } int main() { std::thread worker(worker_thread); std::this_thread::sleep_for(std::chrono::seconds(2)); { std::lock_guard<std::mutex> lock(mtx); std::cout << "Main thread notifying worker thread." << std::endl; ready = true; } cv.notify_one(); worker.join(); return 0; } ``` 在这个示例中,工作线程等待条件变量 ready 为 true,如果为 false,它会被阻塞在 cv.wait() 中。主线程等待2秒后,设置 ready 为 true,并调用 cv.notify_one() 来通知等待的工作线程醒来。工作线程被唤醒后,输出相应的信息。 通过使用 condition_variablenotify_one(),我们可以实现线程间的有效协调和同步,使得在某个条件满足时,线程能够及时醒来执行相应的任务。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值