I believe the solution introduces a race condition when there are more than 1 producer threads.
While the exercise describes only 1 producer thread, I would say it is still a bit misleading for the reader (if I am correct of course.).
Do you agree?
val producer = thread {
var x = 0
while (x < 15) {
if (syncVar.isEmpty) {
syncVar.put(x)
x = x + 1
}
}
}
class SyncVar[T] {
private var empty: Boolean = true
private var x: T = null.asInstanceOf[T]
def put(x: T): Unit = this.synchronized {
if (!empty) throw new Exception("must be empty")
else {
empty = false
this.x = x
}
}
def isEmpty = synchronized {
empty
}
[not shown code]
}
The call to methods isEmpty and put(x:T) is synchronized. However on the producer thread, they are called on separate lines. Is the following possible:
- Some producer Thread-1 calls the method
isEmpty, obtaining the monitor of the syncVar instance.
- The
isEmptymethod returns true.
- The producer Thread-1 releases the monitor over the syncVar instance.
- Some other producer Thread-2 calls the same method
isEmpty on the same syncVar instance.
- It also obtains the value of
true.
- Producer Thread-2 calls method
put(x:T), obtaining the monitor, and effectively inserting a value.
- Producer Thread-1 calls method
put(x:T), obtains the monitor, but because the syncVar variable x is no longer empty, due to step 6, if throws an exception.
I believe the solution introduces a race condition when there are more than 1 producer threads.
While the exercise describes only 1 producer thread, I would say it is still a bit misleading for the reader (if I am correct of course.).
Do you agree?
The call to methods
isEmptyandput(x:T)is synchronized. However on the producer thread, they are called on separate lines. Is the following possible:isEmpty, obtaining the monitor of the syncVar instance.isEmptymethod returnstrue.isEmptyon the same syncVar instance.true.put(x:T), obtaining the monitor, and effectively inserting a value.put(x:T), obtains the monitor, but because thesyncVarvariablexis no longer empty, due to step 6, if throws an exception.