【发布时间】:2015-05-26 20:34:24
【问题描述】:
你知道java中的同步块是否保证是原子的吗?
想象下面的案例
线程_1,2:
synchronized(object){object.modify();}
(对象是共享变量。)
想象 thread_M 会改变对对象的引用
synchronized(object){object = new Object()}
现在假设线程 1 和 2 正在竞争获取对象的锁定
有没有可能发生以下情况:
1. Thread1:读取旧对象
2. ThreadM:修改对象引用并释放旧对象锁
3. Thread2:读取新对象;检查锁;锁定它
4. Thread1: check lock (ok cos old object was read);锁定它
现在两个线程都有一个锁并修改相同的(新)对象
所以要具体说明我的问题 - 在某个地方保证同步(对象)中的步骤(1 和 4)是原子的(如步骤 3 中所述)?
【问题讨论】:
-
同步块不是原子的!但它们通过提供适当的锁定机制来帮助防止竞争条件。
-
@jsn 你是什么意思他们不是原子的?在同一对象的同步块上运行的两个线程将彼此原子地完成。
-
@JohnVint 另一个线程可能在同步块的语句之间调度,因此它不是一个不可打印的全部成功或失败操作。
-
@jsn:我知道其他线程可能会运行。当然我的问题只与同步的“对象”有关。如果对象是最终的,那么显然没有 2 个同步块能够进入同步(对象)。关于线程 1,2,它应该是“原子的”(我会说不是交错)。但问题是,如果 Thread_M 可以更改对象引用本身(尽管在同步块中),锁定过程是否安全。
-
@JohnVint:“同一对象的同步块”是什么意思?块(即代码)不属于对象,块属于类。 OP 想知道两个线程如何同时进入同一个同步块。答案是,他们可以在不同对象上同步时做到这一点。在上面的示例中,这是无意中发生的,因为程序员认为
synchronized(object) { ... }对 变量 进行操作,而实际上它是在对变量恰好在块被引用的瞬间引用的对象进行操作输入。
标签: java multithreading synchronization synchronized