Mutexes around single word read and writes
If you have a multi-threaded application with a word variable shared between threads (ie - 32-bit data type on a 32-bit system), is it necessary to prot开发者_高级运维ect reads and writes to that word with a mutex?
Rather than talk about caches, multicore, out-of-order execution, etc. I'll just offer a simple example to illustrate why you'd want to use a mutex (or some other mutual exclusion technique, e.g. interrupt manipulation, etc.)
In order to increment a variable by one - at least on most architectures I deal with these days - you have to read the value from memory to a register, adjust the value in the register, and write it back to memory. Suppose we have 2 threads, high-priority A, and low priority B. Take this scenario:
- Thread B reads "x" from memory into a register (value is 5).
- Thread B increments the register to value 6.
- Thread A pre-empts Thread B.
- Thread A reads "x" into a register (value is still 5 in memory, right?).
- Thread A increments register to value 6.
- Thread A writes value 6 back to memory
- Thread A goes to sleep.
- Thread B wakes up, and writes its register value 6 back to memory.
Now both threads incremented the value, but it only went up by one.
If this was the elevator floor number, the number of heart beats sensed, or the space shuttle countdown value (OK, that would be a decrement), we might have ourselves a problem.
Note that there are some architectures (usually CISC) that can do this increment operation atomically, it's better to not make this assumption (hello, portability & correctness).
Note: In some cases - but don't do this - you can get away without a mutex if you have one writer & multiple readers. For example, maybe an ISR increments a tick count or whatever, and other threads/tasks come by & read it every so often.
I guess the point I want to make is that it's always a good idea to protect shared data, even if you think you can get away without it. If you want to "go commando", you REALLY have to know what you're doing, and even then, the same code could break tomorrow when it's ported to a new architecture.
In general, yes, you should synchronize access with a mutex. Even if you believe a write to a memory location will be "atomic", the CPU may re-order instructions that read and write to that memory, causing unwanted behavior. Also, on a multi-core or mutli-CPU system, a write to a shared memory location may not be immediately visible to other cores/CPUs without synchronization.
For more information see the Wikipedia article for Memory Barrier.
精彩评论