编写同步方法java

时间:2014-11-24 20:50:19

标签: java

我无法理解为什么没有线程永远不会进入方法等待

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();    
    }
}

在我的代码中,因为我可以防止由睡眠写入的模拟方法引起的饥饿问题?因为如果一个线程长时间处于睡眠状态,那么永远不会写一个你在短时间内入睡的线程

2 个答案:

答案 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()工作的环境中。)