我有两个线程,在linux上使用C pthreads。其中一个写入数据,另一个正在读取数据。我正在使用一个变量来允许读取线程,当允许读取时,写入一个是允许的。因此,互斥锁适用于这个名为“newData”的布尔变量。我的问题是:我是否需要在“if”条件内的访问周围锁定/解锁互斥锁?两种方式都有效,但我认为只是因为在这个变量上重写写/读的可能性很小。我展示了两种替代方案来更好地解释我的问题:
主题1:
pthread_mutex_lock( &lattice_mutex );
if (!newData) {
pthread_mutex_unlock( &lattice_mutex );
uchar *lattice_pos = lattice;
int i;
for(i=0; i<size; i++) {
*lattice_pos = rand()%CHAR_MAX;
lattice_pos++;
}
pthread_mutex_lock( &lattice_mutex );
newData = TRUE;
pthread_mutex_unlock( &lattice_mutex );
} else {
pthread_mutex_unlock( &lattice_mutex );
}
主题2:
pthread_mutex_lock( &lattice_mutex );
if(newData) {
pthread_mutex_unlock( &lattice_mutex );
renderUpdate();
pthread_mutex_lock( &lattice_mutex );
newData = FALSE;
pthread_mutex_unlock( &lattice_mutex );
} else {
pthread_mutex_unlock( &lattice_mutex );
}
第二个版本,有效,但我不知道它是否正确:
主题1:
if (!newData) {
uchar *lattice_pos = lattice;
int i;
for(i=0; i<size; i++) {
*lattice_pos = rand()%CHAR_MAX;
lattice_pos++;
}
pthread_mutex_lock( &lattice_mutex );
newData = TRUE;
pthread_mutex_unlock( &lattice_mutex );
}
主题2:
if(newData) {
renderUpdate();
pthread_mutex_lock( &lattice_mutex );
newData = FALSE;
pthread_mutex_unlock( &lattice_mutex );
}
答案 0 :(得分:4)
这是从你的第一个版本派生出来的 - 它有点简单。
pthread_mutex_lock(&lattice_mutex);
if (!newData) {
pthread_mutex_unlock(&lattice_mutex); // Omit?
uchar *lattice_pos = lattice;
int i;
for (i = 0; i < size; i++)
*lattice_pos++ = rand() % CHAR_MAX;
pthread_mutex_lock(&lattice_mutex); // Omit?
newData = TRUE;
}
pthread_mutex_unlock(&lattice_mutex);
pthread_mutex_lock(&lattice_mutex);
if (newData) {
pthread_mutex_unlock(&lattice_mutex); // Omit?
renderUpdate();
pthread_mutex_lock(&lattice_mutex); // Omit?
newData = FALSE;
}
pthread_mutex_unlock(&lattice_mutex);
这取决于格子信息的确切使用方式,但是考虑到互斥锁的名称,我认为在修改晶格时应该保持锁定状态,因此标记为“忽略”的两对线会被锁定。应该删除。否则,格子不会受到并发访问的保护。
补充:我认为第二个版本是错误的 - 它没有正确保护晶格。
答案 1 :(得分:3)
第一个版本是正确的,您需要在写入和读取时使用互斥锁。
然而,AFAIK,几乎所有架构都对一个数据单元(例如int)原子进行简单的读写访问。但请注意,在内存排序较弱的体系结构中,您可能会遇到一些问题,例如在缓冲区实际包含数据之前将“buffer-full”标志设置为true。
请注意,代码可能不是您可以做的最好的,因为它永远不会休眠(使用繁忙的等待)。如果要等待任一线程中的数据,则必须使用带有互斥锁的条件变量。