我只是好奇,线程T1是否可能部分执行同步块,然后释放对象上的锁,而另一个线程T2则执行相同的块?就像这样:
line1: synchronized(this){
line2: if(INSTANCE == null)
line3: INSTANCE = new Object(); //say a variable is initialized
line4: return INSTANCE;
line5: }线程T1是否可能获取当前对象(this)上的锁并执行line1和line2。然后线程T1被线程T2抢占,T1释放锁,T2获取this上的锁并执行相同的块(所有lines1到5)。然后线程T1再次获取锁并继续从line3执行?
基本上,T1会将INSTANCE视为null,T2也会将其视为null,并且每个T2都将创建一个新对象。
如果这是不可能的,谁能解释为什么不呢?
增编:
谢谢大家的回答。我的问题有点误导。我要问的是,一旦线程执行同步块,它就可以在执行整个块之前释放锁(不是显式调用wait(),而是依赖于进程)吗?JLS或JVM中是否有保证一旦线程开始执行同步块,对象上的锁直到块结束时才会释放?我的理解是同步保证没有任何两个线程可以同时执行块(或其他同步方法/块),但是锁一直保持到块的末尾。这是很明显的,但它是否在JLS中指定?
发布于 2014-12-18 20:46:19
线程抢占不会导致抢占线程释放其锁。如果是的话锁就一文不值了。synchronized块的全部要点是,它将禁止其他线程在同一对象上同步,直到线程释放锁为止(通过离开synchronized块)。
发布于 2014-12-18 21:17:46
即使线程被抢占,它也不会释放锁。锁还在。如果另一个线程出现,它将阻塞(停止运行),直到锁被释放,即使原来的线程在释放锁之前被抢占了好几次。基本上,几乎任何类型的锁都有堆中的一些存储,这些存储被写入以指示存在锁。它是永久的,直到线程或系统写入一个不同的值来指示锁是空闲的。
当然,编写允许访问实例或字段而不使用锁的代码是可能的,但这是一个编码错误。原始线程也有可能提前退出块(比如抛出异常) --这会释放锁,其他线程也可以继续正常运行。
发布于 2014-12-18 20:48:09
我很确定第二个线程不可能在第一个线程执行整个块之前进入synchronize块。在获取对象的锁后,所有试图输入同步代码的其他线程都将被阻塞。
请参阅这里的更多信息:http://tutorials.jenkov.com/java-concurrency/synchronized.html
https://stackoverflow.com/questions/27555325
复制相似问题