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