Imagine, if you will, that you are a programmer and somebody has asked you to write an application that counts cars in intersections. You have webcams mounted on top of the traffic lights and it sends you a message when it sees a car. You have saved somewhere a count of all the cars so far. So, when it tells you it sees a car, you go find that number, add one to it and write down the new number. There is more than one camera in the intersections, though and while some cars are travelling north, others are travelling south at the same time. What if two cameras see different cars at the same time?
- Camera one sees a car and the programme listening to it goes and finds the count of cars so far, which is 75.
- Camera two sees a car and the programme listening to it goes and finds the count of cars so far, which is 75.
- Camera one’s programme adds one to the total and gets 76.
- Camera two’s programme adds one to the total and gets 76.
- Camera one’s programme saves it’s new total.
- Camera two’s programme saves it’s new total.
- You go to look how many cars have been through the intersection and the number recorded is 76.
Camera one and camera two are operating separately from each other at the same time. They are sperate threads. when two of them are trying to change the same resource at the same time, you get something called a race condition. Will the first thread finish before the second thread clobbers it’s changes? The race is on!
Fortunately, there is a solution to this problem: semaphores! Lets’ say you are trying to update your traffic count with SuperCollider:
( var traffic_count, camera1, camera2, semaphore, action; traffic_count = 0; semaphore = Semaphore.new(1); camera1 = TrafficCounterCamera(north); camera2 = TrafficCounterCamera(south); action = { // this will be called when a car is seen Task({ semaphore.wait; // only one thread can get past this point at a time traffic_count = traffic_count +1; semaphore.signal; // relinquish control of the semaphore traffic_count.postln; }).play; }; camera1.action = action; camera2.action = action; )
You need to make a new Semaphore before you use it. By default, they allow one thread through at a time, but you can change the argument to 2 or 3 or whatever number you want.
When your code encounters a semaphore.wait, the thread will pause and wait until it’s turn to procede. Only one thread will be allowed past that line at a time. If both cameras update at the exact same time, one of them will have to wait until the other says it’s good to go ahead.
semaphore.signal is how that thread says it’s good to go ahead. The code in between those lines can only be accessed by a single thread at a time. the traffic_count.postln line is outside the seamphore because it’s not making a change to anything, so it’s safe to read it outside of the semaphore.
So when you have two seperate threads trying to change something at the same time, semaphors can help you out! This sort of situation can arrive with GUI objects, or with OSC messages, HID objects or anything with an action method.
Be thread-safe!
Fun fact: the spanish version of the word "semaphore", 'semáforo', means 'traffic lights'.
themoreyouknow