两个同步的语句。他们是如何工作的?

时间:2013-02-25 11:25:08

标签: java multithreading

我正在尝试在另一个方法中使用synchronized语句运行一个方法。

MyClass的

public class MyClass {

    private Object lockObject = new Object();

    public void testFirst() {
        synchronized (lockObject) {
            System.out.println("Entered testFirst() sync");
            testSecond();
            System.out.println("Leaving testFirst() sync");
        }
    }

    private void testSecond() {
        synchronized (lockObject) {
            System.out.println("Entered testSecond() sync");
        }
    }

}

主要

package com.replanet;

public class Main {

    public static void main(String[] args) {

        MyClass myClass = new MyClass();
        myClass.testFirst();
    }

}

输出

Entered testFirst() sync
Entered testSecond() sync
Leaving testFirst() sync

我期待另一个输出。

Entered testFirst() sync
Leaving testFirst() sync
Entered testSecond() sync

为什么testSecond()不会等到testFirst()完成工作?

6 个答案:

答案 0 :(得分:4)

您看到这种看似奇怪的行为,因为每个锁与请求它的线程相关联,一旦您获得锁定,您就会保留它直到您解锁。

在你的代码中,你获得了两次相同的锁,所以第二次尝试会立即成功,因为你已经拥有它。

请参阅here以获取参考:

  

当一个线程正在为一个对象执行一个synchronized方法时,所有其他线程会调用同一个对象块的同步方法(暂停执行),直到第一个线程完成该对象为止。

答案 1 :(得分:3)

由于要输入第一个synchronized部分,您必须锁定对象lockObject,当您到达第二个synchronized部分时,您仍然可以继续使用它。运行testFirst时,synchronized中的testSecond块不会发生任何变化。

答案 2 :(得分:2)

要记住的一些事项:

  • synchronized块是可重入的:当您通过synchronized语句保持锁定时,您可以使用同一个监视器输入另一个synchronized块 - 在您的情况下,没有什么可以阻止您调用来自testSecond
  • testFirst
  • 现在想象两个方法使用不同的监视器,你仍然会得到相同的输出,因为没有其他线程会持有testSecond的锁
  • IF 这2个方法使用了两个不同的锁 AND 另一个线程持有testSecond中使用的锁testFirst的执行不会跳过拨打testSecond并继续前进,它会阻止,直到锁定再次可用

答案 3 :(得分:1)

Beause testSecond() testFirst()

相关联

控制流程完全如下: -

System.out.println("Entered testFirst() sync");
       System.out.println("Entered testSecond() sync");
System.out.println("Leaving testFirst() sync");

答案 4 :(得分:1)

同步是围绕一个称为内在锁或监视器锁的内部实体构建的 每个对象都有一个与之关联的内在锁。按照惯例,需要对对象字段进行独占和一致访问的线程必须在访问对象之前获取对象的内部锁,然后在完成它们时释放内部锁。据说一个线程在获得锁定和释放锁定之间拥有内在锁定。只要一个线程拥有一个内部锁,没有其他线程可以获得相同的锁。另一个线程在尝试获取锁时会阻塞。

所以你的线程是lockObject的所有者,因此它可以使用lockObject

进入块内的所有代码

答案 5 :(得分:0)

我编辑了我发布的代码。同步语句有意义,不是吗?

<强> MyClass的

public class MyClass {

    private Object lockObject = new Object();

    public void testFirst() throws InterruptedException {
        // Here is something that should not be synchronized 
        synchronized (lockObject) {
            System.out.println("testFirst() is about to fall asleep. "
                    + Thread.currentThread().getName());
            Thread.sleep(2000);
            System.out.println("testFirst() woke up. " + Thread.currentThread().getName());
        }
    }

}

<强> MyThread的

public class MyThread extends Thread {

    private MyClass myClass;

    public MyThread(MyClass myClass) {
        this.myClass = myClass;
    }

    @Override
    public void run() {
        try {
            myClass.testFirst();
        } catch (InterruptedException e) {
            interrupt();
        }
        super.run();
    }

}

<强>用法

package com.replanet;

public class Main {

    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        MyThread mThread = new MyThread(myClass);
        MyThread anotherThread = new MyThread(myClass);
        mThread.start();
        anotherThread.start();
    }

}

<强>输出

testFirst() is about to fall asleep. Thread-0
testFirst() woke up. Thread-0
testFirst() is about to fall asleep. Thread-1
testFirst() woke up. Thread-1