Lecture 11: Concurrency

Concurrency: motivations for concurrent code. Derivation of Amdahl’s law explaining the need to parallelize as much as possible and the opportunity for language design. Challenges with concurrent code, including liveness, fairness, scalability. Threads and processes. Java Thread basics. The need for mutual exclusion and serialisation. Monitors in Java: locks and synchronize, condition variables with wait() and notify().

Link: Slides.

Homework

You should read Sun’s tutorial on concurrency to get an introduction to the concurrency facilities provided in Java if you don’t already know them well.
Experimentation is essential: try some of the examples inside Netbeans or Eclipse and investigate the facilities for debugging concurrent code.

Try to write your own concurrent program from scratch which implements the Pigeon Fancier specification given in the Link: lecture slides. Post questions and discussion here.

8 Responses to Lecture 11: Concurrency

  1. Chris B says:

    The only part of the homework that provided a challenge was ensuring that the PigeonStuffer did not wait too long on any one Pigeonhole. I solved this using an interrupt. The PigeonStuffer thread loops over the available Pigeonholes attempting to put a fresh pigeon in each hole. Before attempting to call the Pigeonhole’s put method (where it will potentially block for a long time) the stuffer spawns a new thread with a timer. If this timer is allowed to expire then it will interrupt the stuffer thread, causing the stuffer to move onto the next pigeon hole. Thus:

    Thread interupt = new Thread(new StufferInterrupt(Thread.currentThread()));
    interupt.start();
    try {
    hole.put(new Pigeon()); //put a new pigeon in the hole
    interupt.interrupt(); //stop the interrupt
    } catch (InterruptedException e) {
    continue; //try next hole
    }

    Here’s the code for the interrupt:

    public class StufferInterrupt implements Runnable{

    private Thread target;

    public StufferInterrupt(Thread target){
    this.target = target;
    }

    @Override
    public void run() {
    try {
    Thread.sleep(500); //wait for 500ms
    target.interrupt();
    } catch (InterruptedException e) {
    //terminate
    }
    }
    }

    • Chris B says:

      Is this the best way of solving it?

      • Chris B says:

        P.S. If anyone’s interested in the code for my full solution then I can make it available.

      • ianstark says:

        I think so, unless you are going to enhance the “put” method with a timeout, perhaps using wait(long timeout).

        David may have something else smarter in mind, though.

        Spinning up a new thread every time you want a timeout is fairly profligate with threads. Can you reuse the interrupting thread?

        • Chris B says:

          I don’t think wait(long timeout) is useful here because it just causes the stuffer to re-obtain a lock and continue from the position at which it was made to wait. I.e. here it will just loop back and find the still full and wait again. If the hole was not full then it would have already been notify()ed. Whereas the desired result here is for the stuffer to break out of the put() method for this hole and move onto the next.

          The only way I could find to do this was the timed interrupt. You are right, though, about not spawning a new thread every time. I might fix this over the weekend and post the answer.

          Here is the source for my solution at the moment.

          • ianstark says:

            > if the hole was not full then it would have already been notify()ed.

            OK. What I meant was to add a new (overloaded) put(long timeout) method which would time out if the pigeonhole did not become empty soon enough. That itself would need to use wait(long timeout), and would not have the loop around that regular put() has. Would this work?

  2. s0568731 says:

    My implementation using a timeout in the wait() call is here: http://sigmaris.info/trac/browser/PigeonFancier/src/pigeon
    If the timeout is used, a second check is needed (Line 19 in PigeonHole.java) to make sure the hole is empty, as at that point it isn’t possible to tell if we finished wait()ing due to a timeout or if we were notify()ed.

  3. ianstark says:

    You’re right about the second check. You might also want to return some information to the caller, too, indicating whether the put was successful.

    N.B. The wait(timeout), like regular wait(), might in principle just wake up for no reason at all — or might be woken up only to find it does not win the race to the empty pigeonhole. Your put(timeout) will inherit that.