When learning the fundamentals of computer science in school, I found myself failing to grasp the significance of certain concepts. Consider the subject of multi-threading and the dangers of race conditions. A race condition is a situation where a program (or thread) depends on the timing or sequence of another program. I understood it enough to regurgitate the definition for the exam. It was one of those things that wouldn’t really stick unless I experienced it in the “real world.” Recently, I had just that experience.
I am allergic to nuts (and peanuts). Deathly allergic, in fact. Naturally with such a dietary restriction, I do what I can to avoid them: I ask if what I order has nuts, I carry an Epi-Pen (just in case), and I usually abstain from deserts. Unfortunately, I do ingest them from time to time.
I went with my fiancée to Ivanna Cone, the best ice cream shop in Lincoln, NE. If you ask, they give little sample spoons of their flavours. My fiancée asked to try two, “may I please try Ginger Panna Cotta and the Honey Almond?” “Certainly,” answered the ice cream maker, grabbing a spoon to scoop the first flavor out, Ginger Panna Cotta. As my fiancée tasted the first flavor, I thought it would be a reasonable time to submit my request for Vanilla Ice. The woman handed me a spoon of frozen delicatessen. I savored the sweetness and felt the texture of the ice. Meanwhile, my fiancée handed her spoon back and received her second spoon. Can you identify the race condition? Let me try to describe it a little better.
My fiancée requested two flavors: Ginger Panna Cotta and Honey Almond.
The woman received the request. The two flavors were stored in memory. She provided the first sample, Ginger Panna Cotta. The Honey Almond stayed in memory while she waited for my fiancée to finish.
The woman accepted the request. The flavor went into memory, after Honey Almond. Instead of waiting to give my fiancée her flavor, the woman provided me with the next spoon: Honey Almond.
My fiancée finishes her spoon and receives the next spoon, Vanilla Ice.
The texture I felt was not ice but almond. I quickly grabbed a napkin and discretely spit out the nuts. Fortunately, this happened quickly enough (and I ate slowly enough) that only my lips were allergized. What could’ve been a really uncomfortable afternoon at the hospital turned out to be a learning lesson.
What could the woman have done to prevent this from happening? Now, don’t get me wrong, I am not saying she is to blame: I should’ve waited my turn and my fiancée probably should’ve abstained from Honey Almond while I was around. But, for the sake of discussion, let’s say the woman is a Java program and patrons are threads. After all, a software developer can’t assume a user will wait to submit another request.
The woman could use a mutex, or a mutual-exclusion semaphore. A mutex allows for one thread to access a block of code at a time. In the ice cream example, my fiancée submitted two requests. She acquires the lock on the block of code that fulfills requests. If I tried to submit a request, I would have to wait until she releases the lock. Consider the following code:
public static void main(String args[]){
IceCreamMaker woman = new IceCreamMaker();
Caller fiancee = new Caller(woman, "Ginger Panna Cotta");
Caller fiancee2 = new Caller(woman, "Honey Almond");
Caller me = new Caller(woman, "Vanilla Ice");
} catch (InterruptedException e){
System.out.println("Interrupted");
class Caller implements Runnable {
public Caller(IceCreamMaker targ, String s){
// synchronized(target) {
} catch (InterruptedException e){
System.out.println("Interrupted");
System.out.print("[" + msg);
} catch (InterruptedException e) {
System.out.println("Interrupted");
Note that I commented out the synchronized block. When this program runs, the output could be any order of the flavors, including the dreaded [Ginger Panna Cotta][Honey Almond][Vanilla Ice]. If we uncomment the synchronized section the output is the safe and desired-well, actually not quite. Even though Caller will be safe from interruption, we still have to worry about the order of the requests.
Now, I must be honest. I spent longer than I wish to say playing with the above code. I wanted to recreate the real life situation in a simple java code but I couldn’t quite do it. Part of the problem was the decision to use fiancee2.t.join() Joining a thread to another one, on some level, dictates the order of the threads. fiancee2 will wait for fiancee to finish. Maybe I could wait() to somehow to recreate the Ivanna Code situation but I feel like that is a little contrived. I would be forcing the threads to go out of order but in a particular way so it wouldn’t really replicate the race condition.
This article was an attempt to describe how important computer science concepts, namely multithreading, may surface in the unexpected ways and places. Thanks for reading!
edit: When I wrote this it didn’t occur to me that the title could be problematic but oh well.