问题: http://blog.joycode.com/gangp/archive/2004/08/14/30672.aspx
Race的根源在于 dataFlag |= tmp; 不是一个Atomic操作。这条语句会转换成三条指令:读取dataFlag, dataFlag | tmp,设置dataFlag。
下面假设有三个线程同时执行。dataFlag 为0,CheckSwitch1和CheckSwitch2返回true。
Thread 1: 调用IsSwitch1On
if ((dataFlag & SwitchFlags.Switch1Ready) == 0) { // 条件为True
SwitchFlags tmp = SwitchFlags.Switch1Ready;
if(CheckSwitch1()) tmp |= SwitchFlags.Switch1On;
// tmp 为SwitchFlags.Switch1On | SwitchFlags.Switch1Ready;
dataFlag |= tmp; // 在读取dataFlag后失去控制权(context switch)
―――――――――
…
Thread 2: 调用IsSwitch2On
if ((dataFlag & SwitchFlags.Switch2Ready) == 0) { // 条件为True
SwitchFlags tmp = SwitchFlags.Switch2Ready;
if(CheckSwitch2()) tmp |= SwitchFlags.Switch2On;
dataFlag |= tmp; // dataFlag被设置为Switch2On | Switch2Ready;
return (tmp & SwitchFlags.Switch2On) != 0; //返回True
}
Thread 3: 调用IsSwitch2On
if ((dataFlag & SwitchFlags.Switch2Ready) == 0) { // 条件为False
…
}
―――――――――
//在此失去控制权(context switch)
return (dataFlag & SwitchFlags.Switch2On) != 0;
Thread 1:
…
dataFlag |= tmp; // dataFlag 的值被设置为Switch1On | Switch1Ready;
…
Thread 3:
return (dataFlag & SwitchFlags.Switch2On) != 0; //返回False
解决的方案有:(1)使用独立的变量存储不同的Switch的值。(2)在修改共享变量时使用Interlocked方法或lock。
打印 | 张贴于 2004-08-22 02:55:00 | Tag:暂无标签
留言反馈