Running with Code Like with scissors, only more dangerous


Teaching Synchronization at University

Posted by Rob

I enrolled in the software engineering program at Arizona State, primarily because that program was willing to take me without having completed an undergraduate degree in computer science (the M.S. Computer Science and M.C.S. programs were not).  But as I went through the process I decided that I wanted to complete a thesis instead of a project, and I found a topic that I wanted to pursue that was clearly out of the realm of what I would consider software “engineering.”  So I began working on undergraduate coursework to make up the deficiencies; the first course I took was Operating Systems.  I thought that we would be actually creating a primitive operating system in the class and was consequently very excited (I’ve read a lot about the topic and have had friends who have worked on them, but I never have myself) – it turned out to be somewhat less exciting, but not too bad to talk about the way OSes allocate memory, manage resources, and provide synchronization services.

Now, I had just built up an app that made extensive use of mutexes to provide non-busy waiting while waiting for external hardware to do some work.  By the time class started, I had a solid understanding of the idea of synchronization primitives – you wait(), and you signal(); waiting allows a thread to pass through if the primitive has free slots and otherwise blocks the thread in a non-busy wait; signalling permits the primitive to allow one or more threads through.

One of our “lab” assignment was to implement a reader-writer lock using Java.  Except that it had mostly been completed already, and if that wasn’t adequate, there was “pseudo-code” to help us out.  Let’s take a look.

public final class Semaphore
   public Semaphore() {
      value = 0;
   public Semaphore(int v) {
      value = v;
   public synchronized void P() {
      while (value <= 0) {
         try {
         catch (InterruptedException e) { }
      value --;
   public synchronized void V() {
   private int value;

This class irritates me for one particular reason: its methods are named P and V.  Now, this class was almost a full year ago, and I wasn’t going to blog about it, except that I stumbled upon the Wikipedia article about semaphores today:

The canonical names P and V come from the initials of Dutch words. V stands for verhogen, or "increase". Several explanations have been given for P (including proberen for "to test", passeer for "pass", probeer "try", and pakken "grab"), but in fact Dijkstra wrote that he intended P to stand for the made-up portmanteau word prolaag, short for probeer te verlagen, or "try-and-decrease" (A less ambiguous, and more accurate, English translation would be "try-to-decrease".) This confusion stems from the unfortunate characteristic of the Dutch language that the words for increase and decrease both begin with the letter V, and the words spelled out in full would be impossibly confusing for non–Dutch-speakers.

I’m fully aware of the great things Edsgar Dijkstra has given to computing.  But let’s also consider that this concept made it into the ALGOL 68 programming language with better names than P and V.  In fact, Java has an intrinsic Semaphore class already built in that has methods named acquire and release.  When I submitted the assignment I chose to rename them to wait() and signal(), but that’s really beside the point.

The point of this whole rant is this: how can we expect students to come out of the university and be effective software developers if we stick to, frankly, archaic naming conventions like this, particularly in assignments which are presented like this by the professor?

See, while I understand the idea of “increase” and “decrease” being legitimate names for a data structure like this when you’re inventing it, now that we’re in the world of object-oriented programming, how can a university course really help its students?  I would submit that a semaphore has basic behaviors: wait and signal (or acquire and release), and that semaphores predefine a fixed number of threads that can acquire them.  But once that number is defined, what do we care how the semaphore is implemented?

We should be helping students get into the habit of following the rules of encapsulation.  Naming the methods of a semaphore “Increase” and “Try to decrease” not only leaks information about the internal mechanics of a semaphore (which may be inaccurate – semaphores could be implemented in hardware, for example, and the internal mechanics of a software semaphore representation of that hardware component may be entirely different), but it also misleads the developer because the names don’t really describe the behavior of what’s happening.  Arguably, wait() doesn’t because the calling thread only waits sometimes (and so I prefer acquire() in this situation), but at least that’s relatively close.

When the wet-behind-the-ears college graduate gets out of school, we don’t expect years upon years of experience from which they may draw.  But I think that it wouldn’t hurt to get these habits in front of students as early and frequently as possible.

Tagged as: No Comments