std::condition_variable::wait_for 的两种重载用法icon-default.png?t=N2N8https://blog.csdn.net/smalbig/article/details/130152253

(以下简称上篇)直观上介绍了 std::condition_variable::wait_for 的使用效果,这篇对没解释清楚的注释、执行结果进行解释。

1.线程创建到函数执行的时间

上篇中线程 th

std::thread th(wait_func, wait_time_out);

创建后 wait_func 不会立即执行,原因是创建线程只是程序向系统申请资源的过程,并不保证函数的执行。线程创建到函数执行的时间,受cpu使用状态影响,最佳情况可能需要 3ms。

创建线程后立即给 flag 赋值,会导致上篇中的 predicate_func 在  wait_func  执行时立刻返回true,也就不会进入等待的过程。

	auto predicate_func = [&]() {
		t2 = std::chrono::steady_clock::now();
		if (flag) {
			flag = false;
			return true;
		}
		else {			
			return false;
		}
	};

2.wait_for 返回值的意义

初识 std::condition_variable::wait_for 时,误以为返回值代表是否超时,其实其真正意义是 predicate_func 的返回值。当 flag 为 true 时,即使已经超时,wait_for 也会返回 true,原因是超时后又调用了一次 predicate_func,并把 predicate_func 的返回值作为 wait_for 的返回值返回。

要想让 wait_for 的返回值代表是否超时,就要这样在锁作用域内 notify_one() and flag = true

		{
			std::lock_guard<std::mutex> lck(mu);
			cv.notify_one();
			flag = true;
		}

3.是否有必要精确获知线程在创建时其函数什么时候执行

答案当然是不必要的,应该通过设计来避免这种需求。一般是预先创建线程,其内部函数通过 wait 等待触发。但是在测试时,为了简单起见还是会有这种操作,即线程创建后希望其函数开始执行(或执行到某一步)后才执行后面的代码。在windows平台测试中,为了获得更精确的延时,可以这样:

void LoopDelay(int delay) {
	std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
	std::chrono::steady_clock::time_point end;
	while (true) {
		end = std::chrono::steady_clock::now();
		if ((end - start).count() / (1000.f * 1000.f) >= delay)
			break;
	}
}

4.predicate_func的执行时机

bool status = cv.wait_for(lck, std::chrono::milliseconds(wait_time_out), predicate_func);

时执行一次,超时   cv.notify_one() 时执行一次。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐