Thread Safety Using the Volatile Keyword

Thread Safety Using the Volatile Keyword
 
As we all know, to write thread-safe code, we need to use locks. Besides this, we have another problem: what if the computer optimizes the code that accesses a variable at a memory address, and break the thread-safety the locks provide? This is possible. See the following example:
 
enter_critical_section(&lock);
(*p)++;
leave_critical_section(&lock);
 
What if the compiler generates (pseudo) code like this:
 
mov lock, ax
push ax
call enter_critical_section
pop ax
mov lock, ax
push ax
call leave_critical_section
pop ax
mov [p], ax
inc ax
mov ax, [p]
 
I guess all of you would feel surprised. Yes. This is not all-right for the compiler to do, since the compiler doesn't know whether `leave_critical_section' uses pointer `p' or not. But consider, if `leave_critical_section' is implemented as an inline function or a macro, would the compiler know this? It's still difficult for the compiler to know because `p' may point to a global variable or a heap memory block, etc., but it may also point to a local variable that may be used by `leave_critical_section'.
 
Then, can we say, if we use a pointer here, we are safe to operate? Let me think it over to see whether we have proof on this. If the compiler simply ignores where the pointer points to, it cannot move the position of the code above. The result must be committed before any following statements.
 
Another thing is, when you use a global variable, never assume it to be safe, because `leave_critical_section' may be inline, and the compiler can safely change the position of (*p)++! The compiler just guarantees the correctness of mono-thread operation, but it doesn't guarantee the correctness of multi-thread operation.
 
Do we need to use volatile pointers? No. We don't. Because we can guarantee every remote memory address assignment (`*p' assignment) in the critical sections be committed immediately (or the compiler should know where `p' points to) and function calls in the critical section be done when they return.
 
However, for safety, what if the compiler can determine where `p' points to? Oh, then use a volatile pointer. In addition, do we need to make function calls in the critical section use volatile pointers? If the compiler is TOO smart, we must! In a case, when a compiler sees this:
 
p = &g_var1; /* a global variable */
*p = 2;
 
It may assume that `p' is always pointing to the variable. To protect against this, we should use a volatile pointer.
 
Fortunately, in modern compilers, the memory barrier is a supported pseudo instruction. The lock/unlock functions in the library contains that instruction, so it is safe to use non-volatile variables/pointers, as long as you use the lock/unlock functions.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值