Java用不同的方法同步同一对象上的块 [英] Java synchronize block on same object in different methods

查看:57
本文介绍了Java用不同的方法同步同一对象上的块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解Java中同步块的概念.从我阅读的文件中,我了解到,如果我们获得一个锁(使用实例变量的同步块),然后我们无法在该类中的同一对象上获取同步锁.但当我尝试使用以下代码片段时,我发现理解是错误的.

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.

即我能够获得锁(同一实例变量上的同步块)在两个不同的位置方法同时进行.当线程启动时,它将运行方法并无限期地等待,并且不会脱离同步堵塞.同时如果我使用相同的方法调用stop方法线程进入同步块并执行通知陈述.我搜索了Java文档,但找不到任何文档.

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.

这是代码段:

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
    } 
}

这是我如何管理MyClass线程的代码段:

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

根据我的理解,当线程启动时,它将获取对"lock"对象(MyClass的run方法中的同步块)的锁定.当我调用stop方法时,它应该无限期地等待,直到run方法从同步块中出来(这种情况下永远不会发生).但是当我执行时,调用stop方法获得了对"lock"对象的锁定,并通知了该对象,从而导致线程关闭.

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.

推荐答案

您的两种方法都使用相同的锁.如果您的MyClass线程恰好在主线程可以调用stop方法之前开始等待,则您的stop方法仍然可以继续,因为等待的线程释放了锁.线程进入wait方法后,它将在休眠之前释放锁定,并且直到退出exit方法时才重新获取该锁定.

Both of your methods use the same lock. If your MyClass thread happens to start waiting before the main thread can call the stop method, your stop method can still proceed, because the waiting thread lets go of the lock. Once a thread enters the wait method it releases the lock before it goes dormant, and doesn't re-acquire the lock until it exits the wait method.

这是相关的 API文档对于Object#wait ,第二段内容涵盖了我上面所描述的关于wait如何释放锁的内容.请注意说明您必须在循环中调用此方法的部分,否则您将遇到顺序依赖性错误,当通知到达主线程时,该依赖关系错误可能导致等待线程挂起,而另一个线程才可以开始等待.

This is the relevant API doc for Object#wait, the second paragraph covers what I described above about how wait releases the lock. Pay attention to the part where it says you have to call this method in a loop, otherwise you have an order-dependency bug that can cause the waiting thread to hang when the notification arrives in the main thread before the other thread can start waiting.

public final void wait()引发InterruptedException

public final void wait() throws InterruptedException

使当前线程等待,直到另一个线程调用此对象的notify()方法或notifyAll()方法.其他话来说,此方法的行为就像它只是执行调用一样等待(0).

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).

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

The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

与在一个参数版本中一样,中断和虚假唤醒是可能,并且此方法应始终在循环中使用:

As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:

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

此方法仅应由拥有者的线程调用该对象的监视器.请参阅notify方法以获取有关以下内容的说明:线程可以成为监视器所有者的方式.

This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.

这是一个玩具示例,但子类Thread和重写Thread方法令人困惑.使用Runnable而不是Thread的原因之一是没有机会通过错误地重写Thread方法而导致问题.

Understood this is a toy example, but subclassing Thread and overriding Thread methods is confusing. One of the reasons for using Runnable instead of Thread is that there's no opportunity to cause problems by mistakenly overriding Thread methods.

这篇关于Java用不同的方法同步同一对象上的块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆