JAVA synchronize block on same object in different methods

时间:2016-03-02 10:54:16

标签: java multithreading concurrency java-threads synchronized-block

I am trying to understand the concept of synchronized blocks in java. As of the documents that I have read, I understood that if we acquire a lock ( synchronized block using an instance variable ) then we cannot acquire a synchronized lock on same object in that class. But when I tried practically using the following snippet I found that my understanding is going wrong.

I.e I am able to acquire lock (synchronized block on same instance variable) in two different methods at the same time. When the thread is started it will go to run method and wait indefinitely and will not come out of the synchronized block. At the same time if I call the stop method using the same thread it goes into the synchronized block and executes notify statement. I searched in the Java doc but I couldn't find any.

This is the code snippet:

public class MyClass extends Thread
{
    private Object lock = new Object(); 
    public void run()
    {
      synchronized(lock)
      {
          lock.wait()
      }
      //other code
    }
    public void stop()
    {
      synchronized(lock)
      {
          lock.notify()
      }
      //other code
    } 
}

Here is the code snippet of how i am managing the MyClass thread:

public class MyClassAdmin 
{
    MyClass _myclass;
    public MyClassAdmin()
    {
        _myclass=new MyClass();
        _myclass.start();
    }
    public void stop()
    {
    _myclass.stop();
    }
    public static void main(String args[])
    {
    MyClassAdmin _myclassAdmin=new MyClassAdmin();
    _myclassAdmin.stop();
    }
}

According to my understanding when the thread is started it will acquire lock on 'lock' object (synchronized block in run method of MyClass). When i call the stop method it should wait indefinitely until the run method comes out of the synchronized block (which will never happen in this case). But when i executed, call to stop method acquired lock on the 'lock' object and notified the object which resulted in shutdown of the thread.

2 个答案:

答案 0 :(得分:1)

您的两种方法都使用相同的锁。如果你的MyClass线程在主线程可以调用stop方法之前开始等待,你的stop方法仍然可以继续,因为等待的线程允许锁定。一旦线程进入wait方法,它就会在它进入休眠状态之前释放锁,并且在它退出wait方法之前不会重新获取锁。

这是相关的API doc for Object#wait,第二段涵盖了我上面描述的等待释放锁的方法。注意它必须在循环中调用此方法的部分,否则您有一个顺序依赖性错误,当通知到达主线程之前,其他线程可以开始等待时,可能导致等待线程挂起。

  

public final void wait()                   抛出InterruptedException

     

导致当前线程等待,直到另一个线程调用   notify()方法或此对象的notifyAll()方法。其他   单词,此方法的行为就像它只是执行调用一样   等待(0)。

     

当前线程必须拥有此对象的监视器。线程发布   此监视器的所有权,并等待另一个线程通知   在这个对象的监视器上等待通过a唤醒的线程   调用notify方法或notifyAll方法。线程然后   等到它可以重新获得监视器的所有权并恢复   执行。

     

在一个参数版本中,中断和虚假唤醒是   可能,这个方法应该总是在循环中使用:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }  
     

此方法只应由作为其所有者的线程调用   这个对象的监视器。有关的说明,请参阅notify方法   线程可以成为监视器所有者的方式。

理解这是一个玩具示例,但是继承Thread和重写Thread方法令人困惑。使用Runnable而不是Thread的原因之一是错误地覆盖Thread方法没有机会导致问题。

答案 1 :(得分:-2)

这是多线程的,它可能永远等待可能不会。 在你的情况下,你很幸运_myclassAdmin.stop();在MyClass开始执行并执行wait();

之后执行

我在将方法stop()名称更改为stop1()之后运行程序,它正在等待。

为了获得一致的行为做一件事,在主要的两个方法调用之间放一个1秒的睡眠,如:

MyClassAdmin _myclassAdmin=new MyClassAdmin();
Thread.sleep(1)
_myclassAdmin.stop();

现在,执行将始终停止。

此外,当线程调用wait()时,它会释放与之关联的监视器,因此任何其他线程都可以获取该锁并发出notify()/ notifyAll()来唤醒等待的线程。这是期待的