我不了解并发性的一件事 - 线程和原子动作。根据docs.oracle,这些操作被指定为原子:
但同时docs.oracle声称递增变量不是原子动作。我以为这是写作:
private int number;
number++;
显然我不明白“读”和“写”是什么意思。
有人可以解释一下并举一个“读”和“写”的例子吗?
编辑:在没有同步的情况下执行此操作时,程序会受到“线程干扰”的影响。所以我明白它不是原子的。但是,当我更改属于这些线程共享的对象的另一个变量时 - 没有任何干扰。 来自此对象的共享变量通过mutator更改。
答案 0 :(得分:4)
为了实现number++
,运行时需要
获取number
的当前值(读取)。
增加该值。
将新值写回number
(写入)。
如果另一个帖子从1开始,当你在2时,则number
的最终值将不正确,因为该线程仍将读取原始值。
如果1,2和3作为原子操作执行(即线程在你完成3之前无法启动1)那么一切都会好的。
答案 1 :(得分:1)
number++
涉及写入是正确的,但它也涉及读取。根据定义,原子操作是完全成功或完全失败的单个操作。由于number++
执行多个独立操作,因此它不是原子操作。但是,有一些API可以将值原子递增为单个操作。在运行时,这些API使用专门的CPU指令,这些指令能够将读取和写入作为单个工作单元执行。
单个读取或写入字对齐,字大小(或更小)的值是原子的,例如:
int x;
x = 5 // write 'x'
5 + x // read 'x'
所以你可能做了解读或写是什么;您可能不认为++
运算符是离散执行的。
在没有同步的情况下执行此操作时,程序会受到“线程干扰”的影响。所以我明白它不是原子的。但是,当我更改属于这些线程共享的对象的另一个变量时 - 没有任何干扰。来自此对象的共享变量通过mutator更改。
如果您在没有同步机制或原子操作的情况下操作共享数据,并且您没有看到数据竞争,那么您只是幸运,或者数据竞争 正在发生,并且您没有注意到。没有看到你的实际代码就很难说。
答案 2 :(得分:0)
递增一个值并引用一个值与递增也不是一回事:这会破坏原子性,因为不仅仅是简单的读或写。