synchronized块没有锁定对象引用

时间:2015-06-25 20:02:50

标签: java multithreading synchronized

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);

d.demo中对MyThread1的来电位于synchronized区块内 d.demo中对MyThread2的调用在<{1}}块中

因此,当synchronized执行时,由于MyThread1阻止,synchronized的监视器应该被锁定,导致d拒绝访问d.demo() {1}}。

但事实并非如此。

预期输出

MyThread2

(输出在Thread 1 starting Inside demo of Thread1 Thread 2 starting 完成之前。)

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

3 个答案:

答案 0 :(得分:6)

  

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

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

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

答案 1 :(得分:3)

synchronization仅发生在Thread1。由于Thread2 synchronize上没有d,因此在Thread1持有锁时允许调用demo()

您似乎误解了synchronized的使用。仅与尝试进入公共对象的同步块的其他线程同步。

答案 2 :(得分:3)

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

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

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

另一个是直接访问

d.demo();

他们已经破坏了这些协作规则,因此您无法承担任何责任。

JLS

中对此进行了解释
  

获取与对象关联的锁定本身并不存在   阻止其他线程访问对象的字段或调用   对象上的非同步方法。其他线程也可以使用   常规中的同步方法或同步语句   实现互斥的方式。