Java以不同方法同步同一对象上的块

Java以不同方法同步同一对象上的块,java,multithreading,concurrency,java-threads,synchronized-block,Java,Multithreading,Concurrency,Java Threads,Synchronized Block,我试图理解java中同步块的概念。 根据我所阅读的文件,我理解如果我们 锁(使用实例变量的同步块),然后 无法获取该类中同一对象的同步锁。但是 当我尝试实际使用以下代码片段时,我发现 理解出了问题 也就是说,我能够获得锁 (同一实例变量上的同步块)位于两个不同的 方法:同时进行实验。当线程启动时,它将运行 方法并无限期等待,并且不会从同步 块同时,如果我使用相同的 线程进入同步块并执行notify 陈述我在Java文档中搜索了一下,但没有找到 这是代码片段: public class MyCla

我试图理解java中同步块的概念。 根据我所阅读的文件,我理解如果我们 锁(使用实例变量的同步块),然后 无法获取该类中同一对象的同步锁。但是 当我尝试实际使用以下代码片段时,我发现 理解出了问题

也就是说,我能够获得锁 (同一实例变量上的同步块)位于两个不同的 方法:同时进行实验。当线程启动时,它将运行 方法并无限期等待,并且不会从同步 块同时,如果我使用相同的 线程进入同步块并执行notify 陈述我在Java文档中搜索了一下,但没有找到

这是代码片段:

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线程的代码片段:

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方法中的synchronized block)。当我调用stop方法时,它应该无限期地等待,直到run方法从synchronized块中出来(这种情况下永远不会发生)。但当我执行时,调用stop方法获取了“lock”对象上的lock,并通知该对象导致线程关闭。

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

在将方法stop()名称更改为stop1()后,我运行了该程序,因为它一直在等待

要获得一致的行为,请在main中的两个方法调用之间放置1秒睡眠,如:

MyClassAdmin _myclassAdmin=new MyClassAdmin();
Thread.sleep(1)
_myclassAdmin.stop();
现在,执行将永远停止


此外,当线程调用wait()时,它会释放与其关联的监视器,因此任何其他线程都可以获得该锁并发出notify()/notifyAll()来唤醒等待的线程。这是因为您的两个方法使用相同的锁。如果MyClass线程恰好在主线程调用stop方法之前开始等待,那么stop方法仍然可以继续,因为等待的线程释放了锁。一旦线程进入wait方法,它就会在休眠前释放锁,直到退出wait方法后才会重新获取锁

这是相关的,第二段介绍了我上面描述的wait如何释放锁。请注意它说您必须在循环中调用此方法的部分,否则您会有一个顺序依赖性错误,当通知到达主线程时,该错误会导致等待线程挂起,而其他线程则会开始等待

公共最终无效等待() 抛出中断异常

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

当前线程必须拥有此对象的监视器。线程释放 此监视器的所有权,并等待另一个线程通知 线程等待此对象的监视器通过 调用notify方法或notifyAll方法。那线呢 等待,直到它可以重新获得监视器的所有权并恢复 执行

在单参数版本中,中断和虚假唤醒是非常重要的 可能,并且此方法应始终在循环中使用:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }  
synchronized(obj){
而()
obj.wait();
…//执行适合条件的操作
}  
此方法只能由作为的所有者的线程调用 此对象的监视器。请参阅notify方法以获取对 线程成为监视器所有者的方式


理解这是一个玩具般的例子,但子类化线程和重写线程方法令人困惑。使用Runnable而不是Thread的原因之一是,错误地重写Thread方法不会导致问题。

您能分享一下您如何创建线程的代码吗?这不是多线程。。您的程序是一个主线程在后面运行的单线程。对于添加睡眠方法的错误建议,您投了赞成票。正确的处理方法是使用一个带有条件变量的循环,如文档中所述。我对同步块的怀疑已经消除。谢谢你的解释@NathanHughes@Rock当你对答案感到满意时,请记得投票,并将答案标记为正确。本着SO的真正精神:)