我试图了解Java中同步块的概念。从我阅读的文档中,我了解到,如果我们获得一个锁(使用实例变量的同步块),那么我们将无法在该类中的同一对象上获得同步锁。但是,当我尝试使用以下代码片段尝试时,我发现我的理解是错误的。
即我可以同时在两种不同的方法中获取锁(同一实例变量上的同步块)。当线程启动时,它将进入运行方法并无限期等待,并且不会从同步块中退出。同时,如果我使用同一线程调用stop方法,它将进入同步块并执行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方法中的同步块)的锁定。当我调用stop方法时,它应该无限期地等待,直到run方法从同步块中出来(这种情况下永远不会发生)。但是当我执行时,调用stop方法获得了对“ lock”对象的锁定,并通知了该对象,从而导致线程关闭。
两种方法都使用相同的锁。如果您的MyClass线程恰好在主线程可以调用stop方法之前开始等待,则您的stop方法仍然可以继续,因为等待的线程释放了锁。一旦线程进入wait方法,它将在休眠之前释放锁定,并且直到退出exit方法才重新获取该锁定。
这是Object#wait的相关API文档,第二段介绍了我上面所描述的关于wait如何释放锁的内容。请注意说明您必须在循环中调用此方法的部分,否则您将遇到顺序依赖性错误,当通知到达主线程时,该依赖关系错误可能导致等待线程挂起,而另一个线程才可以开始等待。
公共最后一个void wait()抛出InterruptedException
使当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。换句话说,此方法的行为与仅执行调用wait(0)的行为完全相同。
当前线程必须拥有该对象的监视器。线程释放此监视器的所有权,并等待直到另一个线程通过调用notify方法或notifyAll方法通知等待在该对象监视器上等待的线程唤醒。然后线程等待,直到它可以重新获得监视器的所有权并恢复执行。
与一个参数版本中一样,可能会产生中断和虚假唤醒,并且应始终在循环中使用此方法:
synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition }
此方法只能由作为该对象的监视器的所有者的线程调用。有关线程可以成为监视器所有者的方式的描述,请参见notify方法。
可以理解,这是一个玩具示例,但是子类化Thread和重写Thread方法是令人困惑的。使用Runnable而不是Thread的原因之一是没有机会通过错误地重写Thread方法而导致问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句