Java同步死锁?

时间:2018-08-17 21:48:47

标签: java scala

我对Java并发还很陌生,并且在尝试使用锁和监视器编写玩具问题时陷入困境。问题的要点是我有一个具有getput方法的类,并且本质上是一个供线程使用和产生的容器。在我一生中,我无法获得正确的同步,要么以死锁或IllegalMonitorStateException结尾。

package concurrency

object ThreadsMain extends App {
  val syncVar = new SyncVar[Int]()

  val producer = new Thread {
    override def run(): Unit = {
      for (x <- 1 to 15) {
        syncVar.synchronized {
          if (!syncVar.isEmpty) {
            syncVar.wait()
          } else {
            syncVar.put(x)
            syncVar.notify()
          }
        }
      }
    }
  }

  producer.run()

  val consumer = new Thread {
    this.setDaemon(true)

    override def run(): Unit = {
      while (true) {
        syncVar.synchronized {
          if (syncVar.isEmpty) {
            syncVar.wait()
          } else {
            println(syncVar.get())
            syncVar.notify()
          }
        }
      }
    }
  }

  consumer.run()

  producer.join()

  consumer.join()
}

class SyncVar[T]() {
  var isEmpty: Boolean = true
  var value: Option[T] = None

  def get(): T = {
    if (isEmpty) throw new Exception("Get from empty SyncVar")
    else {
      val toReturn = value.get
      value = None
      isEmpty = true
      toReturn
    }
  }

  def put(x: T): Unit = {
    if (!isEmpty) throw new Exception("Put on non-empty SyncVar")
    else {
      value = Some(x)
      isEmpty = false
    }
  }
}

1 个答案:

答案 0 :(得分:1)

有一些问题:

  1. 您不应在start上使用run
  2. 如果您使用的是join,则将踏面设置为守护线程是没有意义的。
  3. 在生产者中执行if ... else时,只会得到奇数。应该只是if,其余应该放在if之后(实际上,while是更好的做法)。

我认为这种方式可以实现您想要的代码:

object ThreadsMain extends App {
  val syncVar = new SyncVar[Int]()
  val isDone = new AtomicBoolean(false)

  val producer = new Thread {
    override def run(): Unit = {
      for (x <- 1 to 15) {
        syncVar.synchronized {
          while (!syncVar.isEmpty) {
            syncVar.wait()
          }
          syncVar.put(x)
          syncVar.notify()
        }
      }
      isDone.set(true)
    }
  }

  producer.start()

  val consumer = new Thread {

    override def run(): Unit = {
      while (!isDone.get()) {
        syncVar.synchronized {
          while (syncVar.isEmpty) {
            syncVar.wait()
          }
          println(syncVar.get())
          syncVar.notify()
        }
      }
    }
  }

  consumer.start()

  producer.join()

  consumer.join()
}

class SyncVar[T]() {
  var isEmpty: Boolean = true
  var value: Option[T] = None

  def get(): T = {
    if (isEmpty) throw new Exception("Get from empty SyncVar")
    else {
      val toReturn = value.get
      value = None
      isEmpty = true
      toReturn
    }
  }

  def put(x: T): Unit = {
    if (!isEmpty) throw new Exception("Put on non-empty SyncVar")
    else {
      value = Some(x)
      isEmpty = false
    }
  }
}