2017-05-25 52 views
0

下面是我的代码,其中两个变量在回调时更新,每50ms调用一次。还有一个读取器线程每隔50ms唤醒一次并读取变量。并发读写

经过this后,我猜想会有一些情况,读取的线程会在收到回调时唤醒,因为我在读写时没有锁定相同的互斥量,在这种情况下,它会导致读取的内存不一致。

但是,当我运行它时,这种情况永远不会发生。是不是已经运行了足够长的时间,还是在我的理解中有错误?

recursive_mutex mutex1 
recursive_mutex mutex2 
var1, var2 

//called every 50ms 
onUpdateListener() { 
    lock(mutex1) 
    update var1 
    update var2 
} 

VarReaderThread::readVar() { 
    sleep(50) 
    while(true) { 
     { 
     lock(mutex2) 
     read var1 
     read var2 
     sleep(50) 
     } 
    } 
} 
+0

你的互斥体的'范围'不清楚。 –

+1

为什么要使用这些互斥锁?是否有其他代码访问变量?因为在这种情况下,它们完全没用。 –

+0

您不应该同时书写和阅读,否则可能会遇到不一致的状态(竞争条件)。尽管可以同时执行读取和读取,但您不应该同时写入和写入。写作不混合。使用单独的锁进行读取和写入将无济于事。正如@HenkHolterman在那段代码中暗示那些互斥体什么都不做。 – Persixty

回答

0

数据争用,当两个或更多个线程访问共享数据,其中其中至少一个是其中一个或多个线程可能会遇到不一致的状态的写入操作发生。

提供的代码有两个互斥体,一个用于读取,一个用于写入。 这不会排除一个线程读取共享数据(例子中的var1,var2),而另一个写入它们,或者更准确地说,在一个线程开始写入其中的一个之后并且在某个情况下完成写入另一个之前其中该中间状态将被视为代码逻辑及其目的的参数内的不一致状态。

需要一个mutex使阅读和写作独家。另外,还不清楚为什么递归互斥体已经被声明。只有当一个给定的线程可能遇到要求它获得它已经拥有的互斥体的代码时,才需要这样做。在可能的情况下设计和编码这种情况会更好。已被引入

显式unlock步骤,这可以或可以不被明确地根据编码模型所需(在C需要,使用用C++ std::lock_guard或​​或在Java中finally,等等)。

已引入一些条件来指示正确的终止条件。 while(true)是坏习惯,除非其他条件会优雅地终止它。

更复杂的模型可能会使用'共享互斥',其中多个线程可以在'读'模式下保存它,但只有一个保持'写'模式。这可能需要或不需要某些信号来确保'写入'不会进入活锁,许多读者无休止地阻止'写入'访问。

mutex mutex_v1_v2 //The mutex controlling shared state var1, var2. 
var1, var2 

//called every 50ms 
onUpdateListener() { 
    lock(mutex_v1_v2) 
    update var1 
    update var2 
    unlock(mutex_v1_v2) 
} 

VarReaderThread::readVar() { 
    sleep(50) 
    while(!finished) { 
     lock(mutex_v1_v2) 
     read var1 
     read var2 
     unlock(mutex_v1_v2) 
     sleep(50) //V. V. important to sleep not holding the mutex! 
    } 
}