如何使用pthreads读/写共享变量?

时间:2009-03-03 17:38:29

标签: c pthreads

我有两个线程,在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 );
}

2 个答案:

答案 0 :(得分:4)

这是从你的第一个版本派生出来的 - 它有点简单。

主题1:作家

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);

主题2:读者

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。

请注意,代码可能不是您可以做的最好的,因为它永远不会休眠(使用繁忙的等待)。如果要等待任一线程中的数据,则必须使用带有互斥锁的条件变量。