关于线程安全的一些问题,我认为我理解,但是如果你可以如此善良,我想澄清一下.我编写的特定语言是C,C#和Java.希望在描述特定语言关键字/功能时牢记这些.
1)1位作家,n位读者的案例.在诸如n个线程读取变量的情况下,例如在轮询循环中,并且1个写入器更新此变量,是否需要显式锁定?
考虑:
// thread 1.
volatile bool bWorking = true;
void stopWork() { bWorking = false; }
// thread n
while (bWorking) {...}
在这里,只要有一个内存屏障就足够了,用volatile来实现这个目标吗?根据我的理解,在我上面提到的语言中,对原语的简单读写不会交错,因此不需要显式锁定,但是如果没有一些显式锁定或volatile,则无法保证内存一致性.我的假设在这里是否正确?
2)假设我的上述假设是正确的,那么它只适用于简单的读写操作.那就是bWorking = x …而x = bWorking;是唯一安全的操作? IE复杂的赋值,如一元运算符(,– )在这里是不安全的,因为=,* =等……?
3)我假设如果案例1是正确的,那么当只涉及分配和阅读时,扩展该语句对于n个作者和n个读者来说是否安全是不安全的?
1)在每次读取写入时,从/向“主存储器”更新易失性变量,这意味着更新者线程的更改将在下次读取时被所有读取线程看到.此外,更新是原子的(独立于变量类型).
2)是的,如果您有多个编写器,则组合操作不是线程安全的.对于单个写入线程,没有问题. (volatile关键字确保其他线程可以看到更新.)
3)只要你只分配和读取,volatile就足够了 – 但是如果你有多个写入器,你就不能确定哪个值是“最终”值,或者哪个值将由哪个线程读取.即使是写线程本身也无法可靠地知道它们自己的值被设置. (如果你只有boolean并且只能从true设置为false,那么这里没有问题.)
如果您想要更多控制,请查看java.util.concurrent.atomic包中的类.