LMU ☀️ CMSI 673
CONCURRENT AND DISTRIBUTED PROGRAMMING
HOMEWORK #1

Submit to me, before midnight of the due date above, in a single zip file, containing the files 1.txt, 2.txt, 4.txt and 6.txt with your answers to problems 1, 2, 4, and 6, respectively; livelock.adb, LiveLockExample.java and livelock_example.pl with your answers to problem 3; and PrimePrinter.java and prime_printer.c with your answers to problem 5.

  1. In Java, what happens if you invoke a method on a thread that has completed?
  2. Note that the designers of Java defined that the calls to wait(), notify() and notifyAll() raise an exception if the calling thread does not own the object's monitor. This suggests that the check to see whether a calling thread owns a monitor cannot be made at compile time. Is this true? If so, give an example of a case where the compile time check can not be made. If not, prove that the compiler can always check the legality of wait() and notify() calls.
  3. Write little Ada, Java, and Perl programs that illustrate livelock.
  4. Consider an implementation of the dining philosophers problem in which the first four philosophers always pick up their right chopstick first, but the fifth philosopher always picks up her left chopstick first. Can deadlock occur? Why or why not?
  5. Write, in both Java and C with pthreads, a prime number printing program that constructs -- on the fly -- a chain of threads, each representing a prime number, which filter out all candidates passed through them. Start with a single thread whose job it is to test "inputs" for divisibility by 2. If a number is divisible by 2, go back and listen for more inputs. If a number is not divisible by 2, pass it along to the "next" thread. If there is no "next" thread, create a new thread for that number and assign this new thread as the "next" thread.
  6. Here's a silly little counter class. Counter objects can have a value between 0 and max. Threads can add to or subtract from the counter, but if the new value would be out of range they must block.
    class Counter {
        private int value;
        private int max;
        public Counter(int max) {value = 0; this.max = max;}
        public synchronized void add(int n) {
            while (value+n > max) try {wait();} catch (InterruptedException e) {}
            value += n;
            notifyAll();
        }
        public synchronized void subtract(int n) {
            while (value < n) try {wait();} catch (InterruptedException e) {}
            value -= n;
            notifyAll();
        }
    }
    

    Explain in detail a scenario in which deadlock occurs only if the notifyAll() calls were replaced with notify() calls. That is, there is no deadlock with notifyAll() but there IS deadlock with notify().