我无法理解为什么没有线程永远不会进入方法等待
public class File {
private boolean writing = false;
public synchronized void write()
{
String name = Thread.currentThread().getName();
while(this.writing == true){
System.out.println(name +" wait ");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.writing=true;
System.out.println(name +" writing ");
try{
Thread.sleep((int)(Math.random()*3000));
} catch( InterruptedException e){
e.printStackTrace();
}
this.writing=false;
System.out.println(name +" writing end ");
this.notifyAll();
}
}
public class M_thread extends Thread{
File file;
public M_thread(String name,File f){
super(name);
this.file=f;
}
public void run(){
while(true){
file.write();
}
}
}
public class Main {
public static void main(String[] args) {
File file=new File();
new M_thread("t1",file).start();
new M_thread("t2",file).start();
new M_thread("t3",file).start();
}
}
在我的代码中,因为我可以防止由睡眠写入的模拟方法引起的饥饿问题?因为如果一个线程长时间处于睡眠状态,那么永远不会写一个你在短时间内入睡的线程
答案 0 :(得分:2)
I can not understand why no thread never enters into the method wait
嗯,这相对容易描述:
public synchronized void write() {
// ...
}
这与:
相同public void write() {
synchronized(this) {
// ...
}
}
这意味着,只有一个带有锁this
的线程才能进入此块。由于您使用的是File
:
File file=new File();
new M_thread("t1",file).start();
new M_thread("t2",file).start();
new M_thread("t3",file).start();
..每个Thread在this
上都有相同的对象引用。因此,如果一个线程进入方法write
,则另一个线程必须等到这一个线程释放this
上的锁。
由于writing
的默认值为false
(如果线程离开false
方法,该值将重置为write
),循环while(this.writing == true)
永远不会进入。
答案 1 :(得分:1)
您对同步的理解有点偏,它比您想象的要简单。
您的所有主题都不会同时位于write()
,因为它是synchronized
。因此,没有必要的无关等待/通知逻辑。在this.writing
开始时,{em}永远不会永远为真,因为您在离开每个write()
之前将其设置为false,并且write()
是{ {1}},无论如何都没有线程“跳入”它的中间。也就是说,在write()
为真的那段时间内,任何线程都不会执行synchronized
。
你可以摆脱所有这些逻辑。这已经足够了,因为write()
已经为您完成了这项工作:
this.writing
只需将synchronized
声明为public synchronized void write()
{
String name = Thread.currentThread().getName();
System.out.println(name +" writing ");
Thread.sleep((int)(Math.random()*3000));
System.out.println(name +" writing end ");
}
,就会导致其他致电write()
的线程轮流等待。
请注意,您的synchronized
来电不会在您的示例中抛出write()
,因为您从不致电sleep()
(interruptions do not come out of nowhere)。为简单起见,我省略了异常处理程序。也就是说,如果你要构建在其他情况下使用的代码,那么使它成为InterruptedException
永远不是一个坏主意 - 因为你永远不知道你的代码将来会如何被使用(有人可能会使用)它在他们希望interrupt()
工作的环境中。)