所谓race condition就是因为语句执行顺序的不同,从而造成程序运行结果不同的一种情况。
单线程编程是不可能出现race condition的情况;如果你的共享资源是原子操作,那也不会出现
race condition,但是对于共享资源,哪怕只是一个全局变量的访问,也无法保证其原子性。
在单处理器系统中,真正的原子操作是能够在一个指令周期内完成的操作都能称为原子操作;
而在多处理器系统中,却无法真正做到原子性。
通常race condition只会发生在多线程编程时,对共享资源的访问。
race condition案例分析:
首先定义全局共享变量
int g_pshared_resource;
int get_shared_resource(void)
{
return g_pshared_resource;
}
void set_shared_resource(int value)
{
g_pshared_resource = value;
}
thread_A中执行:
if (get_shared_resource() != null)
{
process_resource();
}
thread_B中执行:
set_shared_resource(value);
所以程序的实际运行顺序就可能会变成:
thread_A get_shared_resource(), get OK;
thread_B set_shared_resource(), set OK;
thread_A process_resource(), 而此时g_pshared_resource已经被修改。
如果是这种case的race condition,此时我们单纯的使用一个mutex无法解决问题。
void get_shared_resource(int* pvalue)
{
mutex_lock();
*pvalue = g_pshared_resource;
mutex_unlock();
}
void set_shared_resource(int value)
{
mutex_lock();
g_pshared_resource = value;
mutex_unlock();
}
上面的代码只能保证对g_pshared_resource这个共享资源的互斥访问,
但是仍然无法解决上述的race condition问题。
正确的做法是需要两把锁,一把锁实现对g_pshared_resource的互斥访问;
另一把锁来实现整个访问过程的原子性。
g_mutex_lock();
if (get_shared_resource() != null)
{
process_resource();
}
g_mutex_unlock();
待解决问题:
软件上如何实现操作的原子性,还有待确认;
对共享变量的读写是否也要实现互斥访问?