Wihtout synchronization you could have this:
Producer Thread Consumer Thread
if (sharedQueue.isEmpty) {
sharedQueue.add(i);
sharedQueue.notifyAll();
sharedQueue.wait()
}
So, even though there is data in the queue, consumer thread would wait potentially forever, because stuff got added between it testing for data, and it starting wait for notification about added data.
Of course there are workarounds, such as timeout on wait
, but these all have polling overhead, latency due to polling interval, ugly code, and so on. No reason to resort to such things when you can just use synchronization.
So why is it not enough, that the queue class is thread safe? Well, a thread safe class is not magic! Being thread safe just means, individual method calls to an instance of that class are thread safe. So for example if two threads do add
at the same time to same instance, it will not corrupt anything, erase one operation with the other, or anything like that.
But if you have multiple threads doing multiple operations, then they can be interleaved, that's the whole point of many threads and pre-emptive multitasking after all! So what happens with interleaved operations, that depends on the operations. For example, many threads doing just add
would add things at some unspecified order, but that's probably ok. But when you don't want operations to happen in "random" order, you need to use synchronization.
As shown by above example, in this case "random" order can result to consumer waiting indefinitely even with data in queue. As a matter of fact, if you ever have sequence "do modification, notify waiters", and waiters doing "see if there's something to do, otherwise wait", you have this same problem, and must use synchronization around both modification-notify and check-wait.
And you get error, because Java requires you to have the lock when notifying, because as explained above, it makes no sense without lock, it would always be an error, a bug. And this is not Java specific, this is fundamental to this type of mechanism, they always require lock, read more at this Wikipedia article section.