Homework 3

Please review the material in Lectures 8, 9, and 10 and then attempt to solve the problem below.

At the URL below, you will find a Git repository that contains two versions of a broken program.

https://github.com/kenbod/5828_HW03_F15

Overview

This program consists of six files. A main routine that creates 10 producers and 10 consumers all sharing an instance of a queue that they use to produce and consume a set of products.

Each producer is configured to create 20 products and then shutdown. Before a producer shuts down, it produces a special type of product that will cause one consumer to also shutdown.

Each consumer is configured to loop until it receives one of the special products. As soon as it receives a special product, it will shut down. The ProductionLine acts as a queue: producers put things on the queue, while consumers take things off the queue.

The main program is configured to get the producers launched, then launch the consumers, and then wait until all of the consumers have finished. Once that happens, it loops through a data structure maintained by the Consumer class to print out all of the product ids that were generated.

The program contains a Monitor that will print out a message about the state of the queue every now and then. It is a demon thread which means that if all of the producers and consumers terminate then the Monitor and main thread will automatically shutdown as well.

When the program functions correctly, we should see 200 products printed out starting with product id 0 and ending with product id 199. There should be no gaps in the product ids that are produced.

The Problem

If you follow the set-up instructions below, you will see that both versions of the program are broken. Usually, the program ends in a state of livelock, where threads are still alive but no progress is being made. In such situations, the program ends in a state where the monitor will print out the same message over and over again. You have to Control-C the application to terminate it.

The only difference between the two programs is that in broken2, the ProductionLine.java file has been modified to add the keyword synchronized to each of its methods. Unfortunately, that approach wasn't able to solve the concurrency problems that exist in this particular implementation of the producer consumer architecture.

Set Up

Please do the following to prepare to work on this problem

  1. Clone the repository above to your own computer.
  2. cd into the broken and broken2 directories and type:
    • ./gradlew build
    • bin/runBroken
  3. In both cases, verify that the code is properly compiled and that the program produces some sort of output in both cases. (Note: you will likely have to Control-C the program in both instances!)
  4. Create a duplicate of the broken directory and rename it fixed
    • Note: on Unix systems, you can use the following command to do this:
    •     cp -r broken fixed
  5. In the new fixed directory, change the name of bin/runBroken to bin/runFixed and edit that file so that it refers to the fixed.jar file.
  6. Execute the command: ./gradlew clean in the fixed directory.

You should now use the fixed directory to try and fix the program so that it runs correctly (see below). You can load this directory structure into an IDE or open two terminal windows; one window should have the fixed directory available while the other window should be located in the directory where all the *.java files are located. Each time you update a file in window 2, you should run the ./gradlew build; bin/runFixed commands in window 1 to monitor your progress.

Note: when trying to fix the program, you may only modify three files:

  1. Consumer.java
  2. Producer.java
  3. ProductionLine.java

You must leave the following three files alone:

  1. Main.java
  2. Monitor.java
  3. Product.java

Questions

In your fixed directory, create a QUESTIONS.md file, that contains the answers to the questions below. Note: Be sure to include the names of all your team mates at the top of this file.

1. Using the material that we have covered in Lectures 8, 9, and 10, explain why the broken program doesn't work. What concurrency-related problems are occuring in this program? If you see the program end in livelock, then describe what is happening with the threads. Why can't they make progress? If you see the program end in another way, such as getting to the point where it prints out the product ids but doesn't include all of them, explain why you think that happened. Note: If you start to add println statements to the Producers and Consumers, you may actually altar the behavior of the program! If you observe this, then also include a discussion on why that happens as well. In your answer, if you want to include snippets of code and/or output to explain what you are seeing, then do so. Use all of Markdown's capabilities to display what you need to explain the concurrency-related problems that you are observing.

2. Now switch your attention to the broken2 program. The only difference between the two programs are the synchronized keywords on the methods contained in ProductionLine.java. For this question, explain why this approach to fixing the program failed. Why is it that synchronizing these methods is not enough. What interactions between the threads are still occuring that cause the program to not be able to produce the correct output? Again, you may use snippets of code and/or output to illustrate your points. The only requirement for this question is that you focus exclusively on issues related to why this particular approach fails to solve the problem. In other words, your answer to this question should be different than your answer to the question above where you are discussing the program and its concurrency problems in general.

3. Now turn your attention to creating an implementation of the program that functions correctly in the fixed directory. In your answer to this question, you should discuss the approach you took to fix the problem and get your version of the program to generate output that is similar to the example_output.txt file that is included with the repo. While your output will not match the example_output.txt file exactly, it should have a simliar structure:

  • The beginning of the output will show the producers starting up, followed by the consumers, and then their outputs interleaving.
  • At some point, Producers will finish their work and announce that they are shutting down.
  • Consumers will then start to shut down as well as they encounter the special Products that indicate that production is done.
  • All of the producers will eventually shutdown followed by the last couple of consumers shutting down as well.
  • The last part of the file is then a list of product ids from 0 to 199 inclusive.
  • The monitor may generate output at any time, so it might have a message that appears in the final list of ids. That is fine, if that happens to you.

A fixed program will then cleanly shutdown and return to the command line prompt.

Note: If you fail to fix the program, that is okay. You will lose some points but it will not be the end of the world. Instead, your answer to question 3 should then include a description of what you attempted to do to fix the problem and your best explanation for why your approach didn't work. Remember, dealing with concurrency is hard. Part of the purpose of this assignment is to provide you with a sense for the weird behaviors that can occur when multiple threads are executing on unprotected data structures!

Logistics

This assignment is worth 100 points. 25 points per question and 25 points for the source code of the fixed program.

You have until the start of lecture on October 6th—Lecture 13—to work on this assignment. When you are done working on this program, please create an archive of the fixed directory and upload it into the Homework 3 dropbox on the D2L website. You can use zip, tar/gzip, or tar/bzip2 to create an archive of the fixed directory. Here are the commands you would use for each of these programs:

  • zip -r fixed fixed.zip
  • tar cvf fixed.tar fixed; gzip -9v fixed.tar
  • tar cvf fixed.tar fixed; bzip2 -9v fixed.tar

Please contact me via e-mail if you have questions about this assignment or ask questions during lecture.


© University of Colorado, Boulder 2015