Lab06: Synchronization

Introduction

This week's lab consists of exercises from your book's chapter. If you have your book, the problems are 6.6, 6.7, and 6.9. Otherwise they'll be listed below.

Setup

First, enter the cs190m directory:

$ cd cs190m

Then, download lab06.zip into the cs190m directory. Run the following commands:

$ unzip lab06.zip
$ cd lab06

For the first two exercises, place your answers in a file called exercises.txt.

Exercise 6.6 (25 pts)

Critical sections can slow down your program by preventing parallel computation. However, the locks used to enforce critical sections can add extra delays on top of this. Design a simple experiment which repeatedly acquires a lock and does some simple operation. Test the running time with and without the lock. See if you can estimate the time needed to acquire a lock in Java on your system. Place your algorithm in a class called Exercise66.

Exercise 6.7 (25 pts)

Design a program which experimentally determines how much time a thread is scheduled to spend running on a CPU before switching to the next thread. To do this, first create a tight loop which runs a large number of iterations, perhaps 1000000 or more. Determine how much time it takes to run a single run of those iterations. Then, write an outer loop which runs the tight loop several times. Each iteration of the outer loop, test to see how much time has passed. When you encounter a large jump in time, typically at least 10 times the amount of time the tight loop usually takes to run to completion, record that time. If you run these loops in multiple threads and average the unusually long times together for each thread, you should be able to find out about how long each thread waits between runs. Using this information, you can estimate how much time each thread is allotted. Bear in mind that this is only an estimation. Some JVM’s will change the amount of CPU time allotted to various threads for various reasons. If you are on a multicore machine, it will be more difficult to interpret your data since some threads will be running concurrently.

Place your algorithm in a a class called Exercise67.

Exercise 6.9 (50 pts)

In Section 6.4 the Buffer class used to implement a solution to the Producer/Consumer problem only has a single lock. When the buffer is empty and a producer puts an item in it, both producers and consumers are woken up. A similar situation happens whenever the buffer is full and a consumer removes an item. Reimplement this solution with two locks so that a producer putting an item into an empty buffer only wakes up consumers and a consumer removing an item from a full buffer only wakes up producers.

The skeleton code you downloaded is for this exercise. The Buffer class has already been implemented as in the book, along with Producer and Consumer classes. The main() method in the Buffer class creates and starts the producer and consumer threads. You can adjust the parameters by changing the constants in each class to test different cases.

Note: Sometimes it seems like the prints will occur out of order. For example, a number may be consumed before it is produced. Why?

Turning In Your Lab

To turn in your lab:

$ cd ~/cs190m/lab06
$ turnin -v -c cs190m -p lab06 *.java *.txt

Getting Help

Many of you will probably run across problems while programming at some point during a lab. If that's the case, here are the resources you should use, in order:

  1. Your textbook
  2. Lecture notes
  3. Java API documentation
  4. Your lab TA