我在求职面试中得到了这个问题,而且在我的生活中我找不到答案(他们最后没有告诉你答案,因为这是笔试):
int thread2_finished = 0;
void t1() {
printf("t1 is running\n");
while (!thread2_finished) { usleep(50); }
printf("t2 is doing stuff\n");
}
void t2() {
printf("t2 is running\n");
sleep(5);
printf("t2 woke up\n");
thread2_finished = 1;
printf("t2 finished\n");
}
我们所知道的是它大部分时间都有效 - 但有时thread1从不存在(不打印最后一条消息)而thread2 确实打印所有消息 - 这怎么可能?< / p>
我猜我错过了一些基本的东西,但我唯一可以想到的问题是缓存 - 就像T1加载值(0)并缓存它,然后立即T2将值更改为1,但由于一些奇怪的原因,T1将继续使用旧的缓存值,但这对我来说似乎很奇怪。
答案 0 :(得分:1)
这样写的代码似乎是正确的(并且它是以逻辑方式)但是如果你使用真实环境它无法正常工作,修复将是 volatile 关键字,但原因是比特复杂,也是因为这个关键字的行为改变了每个语言/编译器,这里是正确的answer
答案 1 :(得分:1)
当t2运行时,您无法保证t1已启动。 sleep
不是正确的线程同步的有效替代。
还可以说thread2_finished
应该是不稳定的。实际上,这并不重要,因为编译器不知道usleep是什么,因此不能假设usleep不会改变全局变量。另一方面,在许多体系结构上,您需要具有比仅更新全局变量更好的同步。在某些其他线程(如果在不同的cpu上运行)可能长时间看不到全局变量的更新值,在其他线程上(如果不是缓存一致)它可能永远不会看到它。操作系统中的锁定原语应提供足够的逻辑,以确保其他线程可以看到来自一个线程的副作用。
简而言之 - 即使这在大多数情况下都有效,但绝不要这样做。使用适当的锁定,条件变量和信号量。