103: Multithreading. Volatile.
Take Up Code - En podcast af Take Up Code: build your own computer games, apps, and robotics with podcasts and live classes
Kategorier:
Volatile is a keyword that allows you to turn off certain optimizations. Unfortunately, it’s also used incorrectly many times as a way to synchronize threads. If you have code that checks a variable for a specific value and you know that the value can be changed through some means that your compiler is not aware of, then declaring the variable to be volatile is perfect. That’s what it’s intended for. Where some developers run into problem though is when trying to use this technique to synchronize the activities between threads. Maybe by creating a variable called done that will be set to true once other variable have been set properly. There are many problems with this that this episode describes. My advice is that while volatile can be useful sometimes, don’t try to use it for any type of thread synchronization. There’s just too many ways it can go wrong. Take the time to use proper thread locking and synchronization methods. Listen to the full episode for more or you can also read the full transcript below. Transcript The dictionary lists several meanings for volatile including a tendency to erupt into violence. That’s not the definition for us. The proper meaning for volatile as it applies to programming is when something has a tendency to change unexpectedly. The exact meaning of volatile gets a little more complicated and it’s worse because different languages have slightly different rules. And even the same language can lead to different behavior if your code needs to be portable across different compilers. The original intention of volatile is simple. Let’s say that you have a program that reads a value from memory but never changes the value itself. The memory value can be changed by some hardware device, maybe some kind of extension card that you installed in your computer. Here’s where you can run into problems. Your compiler will look at your code and try to find places where it can do things better, or simpler, or faster. These are called optimizations and in this case, the compiler will notice that since you never change the value anywhere in your code, then the value must not change. So even though you read the value many times, the compiler may change your code to only read the value once and then just use that same value again and again. We do the same thing in real life. How many times do you actually look up the number for your favorite TV station? Probably never. I know that I just type in the same number that I’m already familiar with. How many times do you actually read each speed limit sign on roads that you drive on every day? It never changes and you just remember what it’s always been, right? It would be very difficult to get halfway through our days if we had to constantly double check everything. So imagine now what a compiler goes through as it analyzes your code. It has the ability to prove that your code never changes a variable. This is more than just a shortcut. This is proof. It’s no wonder then that the compiler chooses to change your code. It’s up to you to let the compiler know that a variable can change beyond its ability to detect. And you do that by marking the variable as volatile. This actually gives you three benefits: ◦ The compiler now knows that the content of a volatile variable is unstable and can change at any time so must not cache the value. It will read the value fresh each time it’s used. ◦ Each write to a volatile variable is observable and must be maintained. Just because the compiler sees no reason to write the same value many times doesn’t mean that this can be removed from your code. There could be something beyond your application that does get value from the multiple writes. ◦ And all operations done with a volatile variable must be done in the same order as in the source code. This does not help maintain the order between volatile and non-volatile variables. But at least the vol