Java Multithreading Exercises

Table of Contents

This is an individual assignment. You may talk about ideas with others in the class, and if this is a programming assignment you may help each other debug code, but the code you type or the analysis that you write should be your own. Any ideas that you get from online should be limited in scope, and you should credit them appropriately via program comments.

This assignment consists of a few exercises to give you some practice with Java multithreading.

1 Clone and review the project

Similarly to the last assignment, use this GitHub Classroom link to accept this assignment. Then adapt the instructions in the last assignment to clone the assignment to your computer. Run all of the tests to see what happens. I've provided the file SumMultithreaded.java as an example of threaded code, so SumThreadTest should run successfully. All of the other tests should fail.

Spend some time looking at the SumMultithreaded.java code. One wacky thing I'm doing is that I'm summing the the trigonometric sine (i.e., Math.sin) values of each element of the array. You might ask why someone would want to add up a whole bunch of sine values. I don't know either. I've done it because calculating a sine value is slow, and so it helps to make clear the advantage of computing this in parallel when measuring timing. The reading merely computers a sum of the numbers in the array which works, but then it fails to achieve a solid speedup when running in parallel.

2 Max sine value

Modify the provided MaxMultithreaded.java file so that it will calculate the maximum sine value of every value in an array. Use SumMultithreaded as an example template. When complete, the tests in MaxValueTest should pass. That said, these tests are not comprehensive. Read through the tests, understand what it's doing, and think about if you need to test anything else.

(Update on 9/13) Important note: The tests for the above two activities involve a speedup test. This test will only execute on the lab computers, because I can't guarantee that it will work on your own computers due to people having different processors with different numbers of cores, multithreading, etc. It is your responsibility to make sure that you run your code on a lab computer to make sure that the tests still pass.

3 Reverse hello

Modify the provided ReverseHelloMultithreaded file so that it creates a thread (let's call it Thread 1). Thread 1 creates another thread (Thread 2); Thread 2 creates Thread 3; and so on, up to Thread 50. Each thread should print "Hello from Thread <num>!", but you should structure your program such that the threads print their greetings in reverse order. When complete, ReverseHelloTest should run successfully. It's critical to note, though, that passing the test isn't sufficient for succeeding at this problem. You could pass the test just by writing code with a loop to count down. You've got to do this correctly via threading, which we'll look at when we grade.

4 Shared counter

Modify the method increment in the provided SharedCounter.java file. This method should launch numThreads threads, and each one should increment the shared counter value numIncrementsPerThread times. Your goal in this assignment is write bad parallel code. This is never a good idea in practice, but I want you to have the experience of seeing this happen. Specifically, I want you to increment the counter with no locks or other mechanisms in place to make sure the counter updates safely. Rather, your goal is to write your code in a way to maximize the likelihood that you'll get a data race, and that your counter won't end up with a value of numThreads * numIncrementsPerThread like it should. Arrange for your code to usually print the wrong answer, despite the fact that each thread on its own increments the counter the correct number of times. (Hint: try using some well-placed calls to Thread.yield() or Thread.sleep().)

Note that succeeding on SharedCounterTest isn't sufficient to get credit for this problem; you could fake it just by writing code that adds the wrong number of times. Again, your goal is to write code that adds the correct number of times within each thread, but still gets the wrong answer overall most of the time.

Regarding grading: Make sure that you run your program on one of the department lab computers, and that it will come up with the wrong answer at least 80% of the time. One challenge in this exercise is that in order to "fail" as intended, it depends on thread timing. Different operating systems or different computers can work differently. Students in the past have written code that fails as intended on their own computers, but not on lab computers. It is your responsibility to make sure that this code does fail as intended on the lab computers. (This helps to point out why the kind of code that you're writing for this assignment is an awful idea – it doesn't run predictably the same way on different computers!)

5 Submit your work

Follow the instructions in the intro assignment on how to push your work to GitHub, making sure to use a commit comment of "finished" to indicate that you're done. When done, visit GitHub, find your repository, and verify that your code was submitted as you intended.


This assignment was originally created by Laura Effinger-Dean; Dave Musicant has made substantial revisions.