问题仅限于X86 / LINUX环境。
一个线程用锁写一个var,其他线程读取这个var而没有锁。 当写入线程解锁时,其他线程可以立即读取新值吗?
volatile int a=0;
/* thread 1(write) */
lock();
a = 10;
unlock();
/* thread 2(read) */
printf("%d",a);
一个线程使用锁读取var,另一个线程写入此var而不使用锁。 写完成后读取线程读取时,是否可以立即读取新值?
volatile int a=0;
/* thread 1(read) */
lock();
printf("%d",a);
unlock();
/* thread 2(write) */
a = 10;
答案 0 :(得分:2)
一个线程用锁写一个var,其他线程读取这个var而没有锁。当写入线程解锁时,其他线程可以立即读取新值吗?
是的,他们可以,但是确保所有读取线程在写入开始之前都不会读取的内容?
一个线程使用锁读取var,另一个线程写入此var而不使用锁。写完成后读取线程读取时,是否可以立即读取新值?
是的,但又是什么确保了读写的顺序?
由于您需要在某种情况下进行操作,因此您需要在此处提供某种形式的同步。最简单的方法是使用信号计数器,如信号量
请注意,volatile
没有为您提供序列的排序,它只能确保对compilres部分没有优化,因此排序仍然是您的责任。
答案 1 :(得分:2)
他们可以,但不能保证。在这两种情况下,你都有 未定义的行为。只要有多个线程访问对象, 并且至少有一个线程修改它,所有访问必须是 同步或未定义的行为结果。
根据C ++ 11和Posix,这是真的。 Linux遵循Posix
规则。在某些版本的VC ++中,volatile
已经扩展了
原子语义学。 (在Posix下,唯一与之相关的语义
volatile
关注信号并longjmp
/ setjmp
。这完全是
在线程中无关紧要且被忽略。)
答案 2 :(得分:0)
小心点。仅仅因为变量被包含在一个锁中,并不意味着如果代码的其他部分不保护对{{{}的访问,那么即使在锁中,其他线程也无法读取它 1}}。在第一个示例中,您锁定了对a
更改的代码的访问权限,但在a
之后您使用了不受保护的读取。在读取之前或期间,另一个线程可能会更改unlock()
的值,从而使您产生非常意外和不可预测的结果。
换句话说,您不是锁定对变量本身的访问,而是将代码中的某些路径限制为互斥
此外,您对a
的使用也很令人担忧。我不确定你为什么使用它,但我猜它不会给你你所期待的。请阅读this以获得更全面的解释。