同步块未锁定对象引用

synchronized block not locking the object reference

class Demo
{
    void demo()
    {
        System.out.println("Inside demo of "+Thread.currentThread().getName());
        try
        {
            Thread.sleep(1000000);
        }
        catch(InterruptedException exc)
        {
            System.out.println(Thread.currentThread().getName()+" interrupted");
        }
    }
}

class MyThread1 implements Runnable
{
    Thread thread;
    Demo d;

    MyThread1(String name, Demo ob)
    {
        d = ob;
        thread = new Thread(this, name);
        thread.start();
    }

    @Override
    public void run()
    {
        System.out.println(thread.getName()+" starting");

        synchronized(d)
        {
            d.demo();
        }

        System.out.println(thread.getName()+" ending");
    }
}

class MyThread2 implements Runnable
{
    Thread thread;
    Demo d;

    MyThread2(String name, Demo ob)
    {
        d = ob;
        thread = new Thread(this, name);
        thread.start();
    }

    @Override
    public void run()
    { 
       System.out.println(thread.getName()+" starting");

       d.demo();

       System.out.println(thread.getName()+" ending");
    }
}

class TimePass
{
    public static void main(String args[])
    {
        Demo d = new Demo();

        MyThread1 mt1 = new MyThread1("Thread 1", d);
        MyThread2 mt2 = new MyThread2("Thread 2", d);
    }
}

输出为

Thread 1 starting

Inside demo of Thread 1

Thread 2 starting

Inside demo of Thread 2

由于Thread.sleep(1000000),执行还没有结束

我已经将 class Demo 的相同实例传递给 classes MyThread1MyThread2.

的构造函数
Demo d = new Demo();
MyThread1 mt1 = new MyThread1("Thread 1", d);
MyThread2 mt2 = new MyThread2("Thread 2", d);

MyThread1 中对 d.demo 的调用在 synchronized 块中。
MyThread2 中对 d.demo 的调用在 synchronized 块中是 而不是

因此,当MyThread1执行时,由于synchronized块,d的监视器应该被锁定,导致拒绝访问d.demo() MyThread2

但这并没有发生。

预期输出是

Thread 1 starting
Inside demo of Thread1
Thread 2 starting

(输出在Thread.sleep(1000000)完成之前。)

所以,我的基本问题是:即使 MyThread1.d.demo() 尚未完成 synchronized 块,MyThread2.d.demo() 如何成功执行?

So, when MyThread1 is executing, due to the synchronized block, the monitor of d should be locked, resulting in denial of access to d.demo() by the MyThread2.

只有当 MyThread2 也有一个 synchronized 块时才会发生这种情况。当一个线程在一个对象上同步时,如果其他线程也尝试在同一对象上同步,它们将被阻塞。如果他们不同步,他们就不会。没有什么可以阻止不同步的线程访问对象。

同步是一种协作机制。它只有在所有线程一起工作时才有效。

synchronization只出现在Thread1。由于 Thread2d 上没有 synchronize,因此允许在 Thread1 持有锁时调用 demo()

您似乎误解了 synchronized 的用法。同步只发生在其他线程试图进入公共对象的同步块时。

同步是一项协作工作。每一方都声明,当另一方处于关键部分时,他们不会。

您只能 synchronized 访问一个线程中 Demo 实例的 demo 方法

synchronized(d)
{
    d.demo();
} 

对方正在直接访问

d.demo();

他们违反了这些协作规则,因此您不能假设任何事情。

这在JLS

中有解释

Acquiring the lock associated with an object does not in itself prevent other threads from accessing fields of the object or invoking un-synchronized methods on the object. Other threads can also use synchronized methods or the synchronized statement in a conventional manner to achieve mutual exclusion.