带有“break”的同步语句

时间:2017-06-02 10:53:05

标签: java multithreading break synchronized

我在编解码器中使用了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;
    }
  }
}

我想知道什么时候执行休息,“锁定”会被释放?

感谢。

4 个答案:

答案 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;
            }
        }
    }
}}
相关问题