我对Java并发还很陌生,并且在尝试使用锁和监视器编写玩具问题时陷入困境。问题的要点是我有一个具有get
和put
方法的类,并且本质上是一个供线程使用和产生的容器。在我一生中,我无法获得正确的同步,要么以死锁或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
}
}
}
答案 0 :(得分:1)
有一些问题:
start
上使用run
。join
,则将踏面设置为守护线程是没有意义的。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
}
}
}