【问题标题】:Simple java synchronization question简单的java同步问题
【发布时间】:2010-06-12 03:34:15
【问题描述】:

在 Groovy 代码中很简单: #!/usr/bin/env groovy

public class test {
  boolean val
  def obj=new Object()

  def dos() {
    val=false
    Thread.start() {
      synchronized(obj) {
    val=true
    obj.notifyAll()
      }
    }
    Thread.sleep(5000)
    synchronized(obj) {
      while (!val) {
    obj.wait()
      }
    }
  }

  static void main(String[] args) {
    def t=new test()
    t.dos()
  }
}

好的,这里是我的问题更详细。

线程 (A) 在单独的线程中启动一个动作,然后等待它完成 -- 好的,这不完全正确,否则可以使用 thread.join()。这个 线程实际上启动了一个任务,然后最终发出 methodOne 信号

线程 (B) 动作完成时我们会收到一个信号

class A {
   private boolean finished

   public synchronized void methodOne() {
       finished=true;
       notifyAll();
   } 

   public void methodTwo() {
       new ThreadThatCallsMethodOneWhenDone().start();
       synchronized(this) {
           while (!finished) {
                 wait();
           }
       }
   }
}

这段代码可以吗,还是我仍然遇到潜在问题?有什么更好的解决方法?

米莎


我想知道哪个是正确的:

选项一

class A {
   public void methodOne() {
       synchronized(this) {
           modifyvalue
           notifyAll()
       }
   }

   public void methodTwo() {
       while (valuenotmodified) {
           synchronized(this) {
              wait()
           }
       }
   }

选项二

class A {
   public void methodOne() {
       modifyvalue
       synchronized(this) {
           notifyAll()
       }
   }

   public void methodTwo() {
       while (valuenotmodified) {
           synchronized(this) {
              wait()
           }
       }
   }

为什么?

【问题讨论】:

  • 21 个问题,3 个接受的答案。他们真的都那么糟糕吗?

标签: java synchronized


【解决方案1】:

我认为两者都很危险,因为您的valuenotmodified 检查是在没有同步的情况下执行的。因此,如果methodOne 修改了值,而methodTwo 正在验证它是否已更改,不知道会发生什么。

而且我认为您的两个“选项”之间没有区别。两者都有这个潜在的问题。

【讨论】:

  • OP 的附加功能,如果您在 wait() 之前 notifyAll(),wait() 可以永远等待,这毫无价值。这可能发生在您的示例中。
【解决方案2】:

所有对“价值”的访问都应该同步:

class A {
   public void methodOne() {
       synchronized(this) {
           modifyvalue
           notifyAll()
       }
   }

   public void methodTwo() {
       synchronized(this) {
           if (valuenotmodified) {
              wait()
           }
       }
   }

}

请注意,这相当于:

class A {
   public synchronized void methodOne() {
       modifyvalue
       notifyAll()
   }

   public synchronized void methodTwo() {
       if (valuenotmodified) {
          wait()
       }
   }
}

【讨论】:

    【解决方案3】:

    并发库可以更好地处理此类问题,该库于 1998 年首次发布,并于 2004 年成为 JDK 5 的一部分。我建议您学习如何使用它们,因为它们通常比 notify/ 更容易使用和理解notifyAll/wait 构造。

    在您的情况下,您可以在其 javadoc 中使用 Condition cmets

    条件因素排除对象 监控方法(等待、通知和 notifyAll) 到不同的对象中 给出具有多个的效果 每个对象的等待集,通过组合 他们使用任意锁 实施。锁代替的地方 使用同步方法和 语句,条件替换 对象监控方法的使用。

    【讨论】:

      猜你喜欢
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多