繁体   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);
    }
}

输出是

线程1开始

线程1的内部演示

线程2开始

线程2的内部演示

由于Thread.sleep(1000000) ,执行尚未结束。

我已经将类Demo的相同实例传递给类MyThread1MyThread2的构造函数。

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

MyThread1d.demo的调用在synchronized块中。
MyThread2d.demo的调用不在 synchronized块中。

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

但是,这没有发生。

预期的输出是

Thread 1 starting
Inside demo of Thread1
Thread 2 starting

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

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

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

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

同步是一种协作机制。 仅当所有线程一起工作时,它才起作用。

synchronization仅发生在Thread1 由于Thread2d上不synchronize ,因此可以在Thread1持有锁的同时调用demo()

你似乎误会使用的synchronized 同步仅在尝试输入公共对象的同步块的其他线程中发生。

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

您仅在一个线程中synchronized访问了Demo实例的demo方法

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

另一个是直接访问它

d.demo();

他们违反了这些协作规则,因此您无法承担任何责任。

JLS中对此进行了解释

获取与对象相关联的锁本身并不能防止其他线程访问该对象的字段或调用该对象上的未同步方法。 其他线程也可以以常规方式使用同步方法或同步语句来实现互斥。

暂无
暂无

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

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