【问题标题】:writing synchronized method java编写同步方法java
【发布时间】:2014-11-24 20:50:18
【问题描述】:

我不明白为什么没有线程永远不会进入方法等待

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

在我的代码中,我可以防止由 sleep 编写的模拟方法引起的饥饿问题吗?因为如果一个线程被长时间休眠,永远不会写比你让一个短时间休眠的线程

【问题讨论】:

  • 我错了,你应该把真与假交换,但这只是一个逻辑错误代码 java 应该更正
  • 请编辑您的问题以反映这一点。
  • 是的,当然..我已经添加了。
  • 离题:File 不是一个类的最佳名称,因为它与一个非常常用的内置类 (java.io.File) 冲突。
  • 如果我没看错的话,“同步”包装器会为您“等待”(字面上将线程排队),所以当每个线程获得执行 writer() 函数的上下文时,再次写入等于false。

标签: java


【解决方案1】:

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

.. 每个线程在this 上都有相同的对象引用。因此,如果一个线程进入方法write,那么另一个线程必须等到这个线程释放this上的锁。 由于writing 的默认值为false(如果线程离开write 方法,该值将被重置为false),循环while(this.writing == true) 将永远不会进入。

【讨论】:

    【解决方案2】:

    你对同步的理解有点偏差,比你想象的要简单。

    您的所有线程都不会同时位于write(),因为它是synchronized。因此,您所拥有的任何多余的等待/通知逻辑都是不必要的。 this.writingwrite() 的开头将永远为真,因为您在离开每个write() 之前将其设置为假,并且由于write()synchronized,因此没有线程“跳跃”无论如何”到它的中间。也就是说,在this.writing 为真期间,任何线程都不会执行write()

    您可以摆脱所有这些逻辑。这已经足够了,因为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() 调用不会抛出 InterruptedException,因为您从不调用 interrupt() (interruptions do not come out of nowhere)。为简单起见,我省略了那个异常处理程序。也就是说,如果您正在构建要在其他情况下使用的代码,那么将其设为interrupt()-safe 绝不是一个坏主意,因为您永远不知道您的代码将来会如何被使用(有人可能会在他们期望 interrupt() 工作的上下文)。

    【讨论】:

      猜你喜欢
      • 2013-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-16
      • 1970-01-01
      • 2011-06-26
      • 2014-07-11
      • 1970-01-01
      相关资源
      最近更新 更多