Today I read the @ leekayak mentioned a problem http://weibo.com/1465082730/znOSZzU4v
I try to explain it in a simple example. First, let's look at a simpler code.
#include "stdio.h"#include "stdlib.h"#include <pthread.h>int f = 0;int x= 0;void* t1(void*){ while(f==0) { if(x!=0) printf("error"); } return NULL;};void* t2(void*){ x=1; f=1; return NULL;};int main(void){ pthread_t* worker = (pthread_t*) malloc(2*sizeof( pthread_t)); pthread_create(&worker[0],NULL,t1,NULL); pthread_create(&worker[1],NULL,t2,NULL); pthread_join(worker[0],NULL); pthread_join(worker[1],NULL); free(worker); return 0;}
We use-O3 to compile and find the problem. Compiler version: GCC version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)
At 400788: The command JMP is sent to itself (_ z2t1pv + 0x18) = 400770 + 18 = 400788, and an endless loop is generated.
This is because the part of the T1 function does not see the expectation that F will be changed. Therefore, the compiler assumes that F will not change, which is equivalent to an infinite loop. In fact, this equivalent is wrong, because F may be modified externally. For example, T2
Therefore, in this case, adding volatile to the definition of F is a concise method, volatile int f = 0; declares that the compiler cannot assume what the f value will be, but must read it.
The other method is to add memory barrier to the display and force the compiler to read it.
While (F = 0) {If (X! = 0) printf ("error ");}
Change
For (_ sync_synchronize (); F = 0 ;__ sync_synchronize ())
{
If (X! = 0) printf ("error ");
}