您知道在java中是否保证同步块是原子的吗?
想象下面的情况
Thread_1,2:
synchronized(object){object.modify();}(对象是共享变量。)
假设thread_M会更改对对象的引用,如
synchronized(object){object = new Object()}现在假设线程1和2正在争夺对象上的锁。
是否有可能发生以下情况:
因此,为了明确我的问题--是否保证在同步(对象)步骤(1和4)中原子化(如步骤3所示)?
发布于 2015-03-23 18:24:51
您可以在object上同步时重新分配object,但我想不出重新分配用于锁定的字段是个好主意。
在线程M退出其同步块之前,其他线程将无法获取object旧值上的锁,但另一个线程将能够在新对象对该线程可见时立即获取该对象上的锁。
线程在释放锁之前所做的修改,保证对随后获得锁的线程是可见的。但是,由于您正在重新分配锁本身,获取线程可能不会看到它已被更改,并获得旧值上的锁。然后他们仍然不会看到object已经被重新分配了。
将object声明为volatile变量将确保其“当前”值用于锁定。但是它不会阻止两个线程并发地修改同一个实例:
为了避免这一切,只需创建一个单独的对象进行锁定,并且永远不要更改它。
发布于 2015-03-23 18:56:16
假设您有一些变量,foo
Foo foo;并且假设它持有对一个对象的引用:
foo = new Foo(...);假设我们有一个synchronized块:
synchronized(foo) {
...
}synchronized keywoord不对变量foo进行操作,也不对同步块中的语句进行操作。
synchronized关键字在这里所做的唯一的事情就是防止其他线程同时在同一个实例上同步。
如果您重新分配变量,foo引用某个不同的实例,而线程A位于块内,那么其他一些线程B将能够同时进入同一个块,因为两个线程中的每个线程都将在不同的实例上进行同步。
发布于 2015-03-23 18:09:34
您正在对" object“指向的对象进行同步,而不是对持有该值的变量进行同步。
然而,因为这两段代码都在您的对象上同步,所以您是安全的--尽管这是一个糟糕的设计模式。
如果您使用同步方法而不是同步代码块,您可能会发现更少的混乱。
而且,这只是我的观点,但是同步(对象)似乎是一个非常糟糕的设计模式。这只是我的意见,但我从来没做过这样的事。
https://stackoverflow.com/questions/29217266
复制相似问题