Goal:
Concurrency.
Bounded buffers can have queue-like behavior (as the examples discussed
in class illustrate)
or stack-like behavior, as the (ungenerified version of)
Bloch's Stack,
example illustrates.
Start with Bloch's stack example and modify it to
make it thread safe for multiple producers
and consumers.
Call your implementation BoundedStack
.
The bounded buffer example discussed in class should provide a very easy-to-follow model. You should evaluate your solution with multiple producers and consumers. (This is what the GTA will do.) Note that for this exercise to make sense, you will need to impose a bound on the size of the stack. The best way to do this is to pass an argument to the constructor with the maximum stack size.
Variants of the examples discussed in class are: BoundedQueueWithGuard.java, BoundedQueue.java. Producer.java, and Consumer.java.
Note: Due to the concurrency aspects, JUnit tests are not required for this assignment.
Technical note:
If you look carefully at the BoundedQueue
code discussed in class,
you will notice that that although the queue part is correct
with respect to concurrency, the access to the other shared resource,
namely the standard output accessed by "print" in the Consumer
and Producer is not!
Because of the different access policies in stacks and queues (lifo vs fifo),
you might actually notice this in the stack version.
The assignment is to get the concurrency on the BoundedStack correct. However, when testing, you should check to see whether you are seeing anomalies with the outputs. There are a variety of ways to address this (by synchronization, of course). I am not requiring any of these for this assignment, but feel free to solve them if you wish.
Bottom line: Even when it's easy, conconcurrency is still hard.