JAVA方法中的互斥线程
我需要提供对类的方法的相互访问,这样每次一个线程就可以执行方法中的代码。 我尝试了下面的解决方案,但我无法理解为什么每次变量“locked”的值都是falseJAVA方法中的互斥线程,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我需要提供对类的方法的相互访问,这样每次一个线程就可以执行方法中的代码。 我尝试了下面的解决方案,但我无法理解为什么每次变量“locked”的值都是false public class MyCommand extends BaseCommand { private static boolean locked=false; @Override public boolean execute() throws Exception { synchronized(MyCommand
public class MyCommand extends BaseCommand {
private static boolean locked=false;
@Override
public boolean execute() throws Exception {
synchronized(MyCommand.class){
while (locked){
wait();
}
locked=true;
//some code with a breakpoint/long blocking operations
locked=false;
notifyAll();
return true;
}
}
我在while语句的开头放置了一个断点,并且locked变量的值总是false,我无法理解为什么。
第二个断点在方法的主体中,我使用它来阻止第一个线程的执行,并查看第二个线程中锁定的变量的值发生了变化,但不幸的是,它没有发生。
因此,作为最终结果,所有线程都能够在没有任何线程安全性的情况下执行此方法。
有没有人知道我如何提供对该方法的独占访问,每次一个线程?同步块中一次只有一个线程,对吗? 在块的开头停止线程,并检查
locked
的值。如果你的线程在块内,那就意味着没有其他线程在块内。如果没有其他线程在里面,那么locked
必须为false,这就是关键所在。为什么你会感到惊讶
你不需要
while(locked)wait()
循环(或者整个locked
的事情)正是因为上述原因-整个“锁定”是通过在你的代码周围同步锁来实现的 同步块中一次只有一个线程,对吗?
在块的开头停止线程,并检查locked
的值。如果你的线程在块内,那就意味着没有其他线程在块内。如果没有其他线程在里面,那么locked
必须为false,这就是关键所在。为什么你会感到惊讶
你不需要while(locked)wait()
循环(或者整个locked
的事情)正是因为上述原因-整个“锁定”是通过在你的代码周围同步锁来实现的 该值始终为false,因为一次只有一个线程正在执行同步块,所以。。。当第一个线程完成时,变量再次为false。。。然后,下一个线程读取false
在这种情况下,我更喜欢使用ReentrantLock,比如:
protected final ReentrantLock myLock= new ReentrantLock();
...
try {
//wait until i have the lock
this.myLock.lock();
//do some stuff
} finally {
//release the lock
this.myLock.unlock();
}
在本文中,您可以看到synch部分和ReentrantLock在性能上的巨大差异:
该值始终为false,因为一次只有一个线程在执行同步块,所以。。。当第一个线程完成时,变量再次为false。。。然后,下一个线程读取false
在这种情况下,我更喜欢使用ReentrantLock,比如:
protected final ReentrantLock myLock= new ReentrantLock();
...
try {
//wait until i have the lock
this.myLock.lock();
//do some stuff
} finally {
//release the lock
this.myLock.unlock();
}
在本文中,您可以看到synch部分和ReentrantLock在性能上的巨大差异:
此.class不是有效的表达式。请修复。如果没有共享的可变数据,那么您的命令是完全线程安全的。怎么做?不修改参考参数的状态;不要创建任何可变的类成员变量。为什么不能只添加synchronized关键字?您不需要锁定的
静态字段syncronized(MyCommand.class)
就足够了。同时拥有同步块和锁定变量的原因是什么?Java的监视器是互斥体。无论如何,我会使用ReentrantLock来代替,这样更好。this.class不是有效的表达式。请修复。如果没有共享的可变数据,那么您的命令是完全线程安全的。怎么做?不修改参考参数的状态;不要创建任何可变的类成员变量。为什么不能只添加synchronized关键字?您不需要锁定的
静态字段syncronized(MyCommand.class)
就足够了。同时拥有同步块和锁定变量的原因是什么?Java的监视器是互斥的。无论如何,我会使用ReentrantLock来代替,这会好得多。谢谢Dima,还有一个问题我注意到我在方法中用块同步(MyClass.class){}实现了互斥,但是我不明白为什么我移除块并在方法声明中加入同步(public synchronized boolean execute())事情停止工作了,你知道为什么吗?@daniele不,我不知道为什么……但如果你想了解更多关于什么是“事情”、你期望它们如何“工作”以及它们“停止工作”时到底会发生什么的细节,我可能会想到一些事情:如果我在指令int a=1的行中添加了一个断点,那么在方法中显式地定义了块synchronized(synchronized(MyClass.class){int a=1;});不管我启动了多少个线程,断点都会中断一个线程,因为块的执行是互斥的(这是我所期望的),而如果我删除同步块并使用类似于:public boolean synchronized execute(){int a=1;}的方法,我会再次将断点放在int a=1行;断点将中断所有线程,这意味着该方法不是以互斥方式执行的,我无法理解区别是什么。因为,在本例中,我希望上述注释中描述的行为与Dima相同,这是另一个问题,我注意到我在方法中实现了与块同步(MyClass.class){}的互斥,但我无法理解为什么在移除块并在方法声明中放入同步时会发生这种情况(public synchronized boolean execute())事情停止工作了,你知道为什么吗?@daniele不,我不知道为什么……但如果你想了解更多关于什么是“事情”、你期望它们如何“工作”以及它们“停止工作”时到底会发生什么的细节,我也许能想出一些办法