What In The Hell Are Race Conditions and Locks

In the context of parallel or concurrent programs, you will often hear the term race condition. This describes a problem when two pieces of code try to modify the same variable (or other location in memory).

Race conditions can be notoriously difficult to find, reproduce and debug.

To start with we have a variable a that is set to 7. I’ll show you what can happen, step-by-step, when two pieces of code try to use and modify that variable.

Both a = a + 35 and a = a – 10 will execute “at the same time”. I have “at the same time” in scare quotes because we don’t really know what “at the same time” means. Computers process instructions sequentially, this means that one operation has to come before the other. Let’s see how that can play out…

From looking at the code in the beginning, you may have guessed that the value of a after these operations would be 42, and that was indeed the intent. However, because of the race condition the value of a ended up being -3. Not at all what we wanted!

Probably the most common way to handle race conditions is to use locks. Here’s how the above process would look using locks…

Locks prevent race conditions by making sure that only one piece of code can access a memory location at any time. Locks can become very complicated to manage and are themselves the source of many bugs. Consider what would happen if some piece of code did not unlock the memory it was modifying! Or worse, did not lock it in the first place, in which case we fall back to the race condition.

Locks are not the only way to handle race conditions (though they are the most common). Another way to handle race conditions is to use immutable variables. This means that no code is allowed to change the value of a. Immutable variables will be the subject of another WITH article, so I won’t explain them here.

GOTO Table of Contents

Tips for a New Programmer

A post I read the other day about learning to program prompted me to jot down a few quick tips based off of my experience learning to program.

Don’t worry about speed

In your first year of programming the chances are near 100% that all of your code will be slow. Don’t bother trying to optimize your programs, spend your time instead on learning and using basic data structures and algorithms.

Challenge yourself, but don’t try to do the impossible.

When you pick projects as a beginning programmer you will be tempted to want to create the next big innovation in software. However this road is long and hard and you will be battered with defeat along the way. Instead, try to pick simple things that you can accomplish in a month or two and are just a little bit outside your abilities.

Don’t worry about the right way to do it, but only at first.

In the beginning you’re going to write bad code. However writing bad code can be a great motivating factor to learn to write better code. For instance, writing code to print each element in an array by hand would be great motivation to learn how to use loops. In the beginning you want to get a feel for programming, what works and what doesn’t and what all those names you hear about actually do in the computer. After you’re comfortable building small toy programs you can start learning the right way to do things.

Stick with one language, for now.

You have probably scoured the internet trying to figure out which language to start with. I’m sure you’ve come across posts by people telling you to learn a lot of languages. I agree with them, any experienced programmer should learn lots of languages (or at least a couple very different ones). However you’re not experienced yet and will only get lost in a sea of syntax. Pick a language and stick with it for a year at least, I recommend Python.

Your first programs should have some kind of visual feedback.

With visual oriented programs like games or GUIs you can see your program performing right in front of your eyes. Not only is this great motivation, as your results are immediately available, it is also a great learning experience. A good place to start is vpython which gives you a 3d world to play in that is very simple to code.

Read code, but read the right code.

Learning to read code is a must. However don’t just grab the sources to Firefox and have at it. To start learning to read code I recommend reading libraries for the language you program in. Libraries are often written in a functional style that doesn’t require you to chase all over the place looking for definitions and keeping state in your head. Of course this can vary widely based on the language/libraries you are reading.

Throw away all the code that you wrote in your first year.

OK that might be a little harsh, you may have a few gems. The vast majority of your code, however, belongs in the trash (or in your archives to bring out for amusement and reminiscing about the old days).

You will find, as you progress through your journey to enlightenment, that when you look back at previous non-trivial code you wrote you will mostly think “Why did I do that!?!” In the case that this is not true you have either reached the pinnacle of enlightenment or have stopped caring about learning new things (it is almost universally the latter).

If you enjoyed this article you may like: Which programming language should I learn

What In The Hell Are Errors

GOTO All What In The Hell Articles

Almost every program you will ever write will have errors.

As soon as we started programming, we found out to our surprise that it wasn’t as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.
-Maurice Wilkes

 

Syntax Errors

Syntax errors are probably the most common errors in programming. Luckily they are usually also the easiest to fix. Most languages will point out syntax errors as soon as you try to run or compile your program. Usually you will be provided with a file and line number of the offending syntax. Some IDEs check your syntax as you type, providing a sort of spell checker for syntax.

Python

def add(x, y)
  return x + y
File "./test.py", line 2
  def add(x, y)
              ^
SyntaxError: invalid syntax

Chicken Scheme

(define add(x y) (+ x y))
Error: during expansion of (define ...) - in `define' - too many arguments: (define add (x y) (+ x y))

        Call history:

        <syntax>          (define add (x y) (+ x y))

 

Type Errors

Type errors occur when your code tries to do things like adding an integer and a string together. Depending on the language you use you may be notified of type errors when compiling your program or while your program is running. Type errors are also very common and are a little bit harder to fix.

Python

def add(x, y):
  return x + y
add(1, "a")
Traceback (most recent call last):
  File "./test.py", line 4, in <module>
    add(1, "a")
  File "./test.py", line 3, in add
    return x + y
TypeError: unsupported operand type(s) for +: 'int' and 'str'

Chicken Scheme

(+ 1 "a")
Error: (+) bad argument type: "a"

        Call history:

        <syntax>          (+ 1 "a")
        <eval>    (+ 1 "a")     <--

 

Logical Errors

Logical errors occur when you write code that performs correctly, but does not give the output that you desire. Logical errors can be the worst kind of bugs. There is rarely any support for detecting them built into the language, as there is technically nothing wrong with the code. These bugs happen somewhat frequently and can range from minor inconvenience to major disruption.

Below is an example of a logical error that would fall into the minor inconvenience category. We’re trying to define a function named add that takes two arguments, adds them together and returns the result. The code we have below does not have any syntax or type errors in it and it is perfectly valid code. However instead of adding the two arguments it subtracts them and we get the answer 0 when we expected the answer to be 4.

Python

def add(x, y):
  return x - y
add(2, 2)
#>>> 4
0

Chicken Scheme

(define (add x y)
  (- x y))
(add 2 2)
;>>> 4
0

 

Errors and Error Handling

Each language will have its own way of representing errors. Some languages provide a mechanism called error handling which let’s you control what happens when an error occurs. We’ll get deeper into errors and error handling in an upcoming WITH article.

GOTO Table of Contents