我在编解码器中使用了synchronized语句,块中有一个“中断”:
for (int j = 0; j < testPathSize; j++) {
synchronized (lock) {
if (kpis.get(j).getDate() > startTimeInMs) {
if (j > 0) {
if ((kpis.get(j).getDate() - startTimeInMs)
> (startTimeInMs - kpis.get(j - 1).getDate())) initTestPath = j - 1;
else initTestPath = j;
} else initTestPath = j;
break;
}
}
}
我想知道什么时候执行休息,“锁定”会被释放?
感谢。
答案 0 :(得分:9)
每当执行超出synchronized
块的范围时,锁将被释放。无论是因为正常的程序流程,break
,异常,还是其他任何方式都超出了块。
有关其工作原理的官方说明可在Java语言规范的第14.19 The synchronized
Statement段中找到。
答案 1 :(得分:3)
这取决于break
取代码的位置:
如果break
结束的循环完全包含在synchronized
块中,则break
将不会释放锁定,例如:
synchronized (thing) {
for (;;) {
break;
}
}
否则,执行将离开synchronized
区域,释放锁定,例如:
for (;;) {
synchronized (thing) {
break;
}
}
规则是当您因任何原因退出synchronized
阻止时释放锁定,或者在锁定对象上调用wait
。
编辑:当synchronized
块位于循环内时,您的代码属于第二类。因此,break
将解除锁定。
答案 2 :(得分:1)
其他答案都是正确的,但它们错过了核心点:您不应该编写将if语句放入同步块的代码到for循环中;然后使用 break 离开那里。
除了“离开sync'块时,锁定消失了”:退后一步,重构代码。
指导模因:single layer of abstraction原则。实际上,你的“块”的每个应该以某种方式进入它自己的方法。另一个可能对此有帮助的原则是:“告诉,不要问”。不要查询对象的某些属性来对该对象的外部属性做出决定。相反,启用该对象自己做出决定。并非总是可行,但通常是将OOP转换为程序编程的关键因素,从而使您的对象模型不那么有用。
如上所述:真正的问题在于您编写了难以阅读代码。对此有点抱歉;在修复时,请确保锁定正确!
答案 3 :(得分:0)
java文档说
synchronized语句(第14.19节)计算对象的引用;然后它会尝试在该对象的监视器上执行锁定操作,并且在锁定操作成功完成之前不会继续进行。执行锁定操作后,将执行synchronized语句的主体。如果正常或突然完成正文的执行,则会在同一监视器上自动执行解锁操作。
同步方法(第8.4.3.6节)在调用时自动执行锁定操作;在锁定操作成功完成之前,它的主体不会执行。如果该方法是实例方法,则它会锁定与调用它的实例关联的监视器(即,在执行方法主体期间将被称为this的对象)。如果方法是静态的,它将锁定与Class对象关联的监视器,该对象表示定义方法的类。如果方法正文的执行正常或突然完成,则会在同一监视器上自动执行解锁操作。
Means是以任何java方式退出的同步块正常或突然锁将被放弃。在这里打破;是一种正常的退出方式。
请参阅下面的示例。
public class LockAndBreak {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 3; i++) {
new Thread1("Thread : " + i, lock).start();
Thread.sleep(2000);
}
}}
class Thread1 extends Thread {
private Object lock;
public Thread1(String name, Object lock) {
super(name);
this.lock = lock;
}
@Override
public void run() {
System.out.println("Running Thread " + this.getName());
int i = 0;
synchronized (lock) {
while (true) {
System.out.println("Printing from thread " + this.getName() + "-->" + i);
i++;
if (i > 9) {
System.out.println("Existing the thread : " + this.getName());
break;
}
}
}
}}