在多核环境中使用原子操作的线程安全性

时间:2016-03-03 11:28:06

标签: java multithreading

我听说单个原子操作是线程安全的,因为当核心处理原子操作时,核心在完成原子操作之前不会做任何其他事情。

例如在32位操作系统的java中,假设有一个可供多个线程访问的变量

 int a; 

线程1写入

a = 3; 

和第2个线程可以写

a = 4; 

写入该变量的线程的顺序可能会改变,因此最终值可以是3或4,但我们可以确定写入int是一个原子操作,因此该变量中的32位不会混合进入一些不可预测的数字

我认为在单核环境中就是这种情况,因为核心在确定原子操作完成之前不会执行另一个线程的代码,

然而,在多核环境中,另一个核心是否可能访问当前核心的原子操作下的变量?从而导致变量中的32位混淆?

2 个答案:

答案 0 :(得分:5)

不 - 这就是原子意味着什么:写入将永远成功“无干扰”。因此,您将读取0(原始值),3或4,但没有其他值。

在多核设置中会发生的情况是,如果线程T1在核心C1上写入3而线程T2在核心C2上写入4,则该值可能仅对进行写入的核心保持可见。因此,您的int可能在C1中的值为3,在C2 中同时为4 。如果有第三个核心C3,它仍然可以看到0的原始值。

为防止出现这种不一致,您需要添加一些同步(例如,通过使int变为volatile)。

答案 1 :(得分:1)

简而言之,示例操作都不是线程安全的。您需要使用原子或同步来授予任何可预测的输出。在给定的示例中,甚至可能在读取线程'a'时将结束为0并且将更新为'3'或'4'。

原子论不只是关于原子性,它们也是关于排序的。而后者是所有并发编程的基石。

请记住,有很多事情可能会出错,而且不仅仅是CPU中发生了什么。编译器还重新排序操作,甚至消除主存储器写入。

我建议您阅读以下链接,了解所有内容的工作原理: