简体   繁体   English

同步块未锁定对象引用

[英]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);
    }
}

The output is 输出是

Thread 1 starting 线程1开始

Inside demo of Thread 1 线程1的内部演示

Thread 2 starting 线程2开始

Inside demo of Thread 2 线程2的内部演示

Due to Thread.sleep(1000000) , the execution is not yet ended. 由于Thread.sleep(1000000) ,执行尚未结束。

I have passed the same instance of class Demo to both the constructors of classes MyThread1 and MyThread2 . 我已经将类Demo的相同实例传递给类MyThread1MyThread2的构造函数。

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

The call to d.demo in MyThread1 is in a synchronized block. MyThread1d.demo的调用在synchronized块中。
The call to d.demo in MyThread2 is not in a synchronized block. MyThread2d.demo的调用不在 synchronized块中。

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 . 因此,在执行MyThread1时,由于synchronized块,应该锁定d的监视器,从而导致MyThread2拒绝访问d.demo()

But this is not happening. 但是,这没有发生。

The expected output is 预期的输出是

Thread 1 starting
Inside demo of Thread1
Thread 2 starting

(The output is before Thread.sleep(1000000) is finished.) (输出在Thread.sleep(1000000)完成之前。)

So, my basic question is: How MyThread2.d.demo() is executing successfully even if MyThread1.d.demo() is not yet finished the synchronized block? 所以,我的基本问题是: 如何MyThread2.d.demo()成功执行,即使MyThread1.d.demo()尚未完成的synchronized块?

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. 因此,在执行MyThread1时,由于存在synchronized块,因此应锁定d的监视器,从而导致MyThread2对d.demo()的访问被拒绝。

That would only happen if MyThread2 also had a synchronized block. 仅当MyThread2也具有synchronized块时,才会发生这种情况。 When one thread is synchronized on an object, other threads will be blocked if they also try to synchronize on that same object. 当一个线程在对象上同步时,如果其他线程也尝试在同一对象上同步,则其他线程将被阻止。 If they don't synchronize, they won't be. 如果他们不同步,它们就不会同步。 There's nothing that stops access to an object from threads that don't synchronize on it. 没有什么可以阻止从不同步对象的线程访问对象的。

Synchronization is a cooperative mechanism. 同步是一种协作机制。 It only works when all threads work together. 仅当所有线程一起工作时,它才起作用。

The synchronization only occurs in Thread1 . synchronization仅发生在Thread1 Since Thread2 does not synchronize on d , it is allowed to invoke demo() while Thread1 holds the lock. 由于Thread2d上不synchronize ,因此可以在Thread1持有锁的同时调用demo()

You seem to be misunderstanding the use of synchronized . 你似乎误会使用的synchronized Synchronization only occurs with other threads trying to enter a synchronized block of the common object. 同步仅在尝试输入公共对象的同步块的其他线程中发生。

Synchronization is a collaborative effort. 同步是一种协作。 Each party states that when another party is in a critical section, they won't be. 每一方都说,当另一方处于关键部分时,他们不会。

You've only synchronized access to the demo method of the Demo instance in one thread 您仅在一个线程中synchronized访问了Demo实例的demo方法

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

The other is accessing it directly 另一个是直接访问它

d.demo();

They've broken these collaboration rules so you can't assume anything. 他们违反了这些协作规则,因此您无法承担任何责任。

This is explained in the JLS 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. 其他线程也可以以常规方式使用同步方法或同步语句来实现互斥。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM