1

我正在编写一个程序,该程序仅演示从有界缓冲区写入和读取,因为它输出预期的值和实际读取的值。当我将 N 定义为低值时,程序按预期执行。但是,当我增加值时,我开始看到意想不到的结果。据我了解,我正在使用两个线程创建数据竞争。

通过查看输出,我认为我已将其范围缩小到大约三个数据竞争示例,如下所示:

  1. 一个线程写入缓冲区,而另一个线程读取。
  2. 两个线程同时写入缓冲区。
  3. 两个线程同时从缓冲区读取。

下面是我的代码。#include 语句的格式真的很奇怪,所以我把它们排除在外。

#define BUFFSIZE 10000
#define N   10000

int Buffer[BUFFSIZE];

int numOccupied = 0;    //# items currently in the buffer
int firstOccupied = 0;  //where first/next value or item is to be found or placed

//Adds a given value to the next position in the buffer
void buffadd(int value)
{

Buffer[firstOccupied + numOccupied++] = value;
}


 int buffrem()
{

numOccupied--;
return(Buffer[firstOccupied++]);

}

void *tcode1(void *empty)
{
int i;

//write N values into the buffer

for(i=0; i<N; i++)
    buffadd(i);
}

void *tcode2(void *empty)
{
int i, val;

//Read N values from the buffer, checking the value read with what is expected for testing

for(i=0; i<N; i++)
{
    val = buffrem();
    if(val != i)
        printf("tcode2: removed %d, expected %d\n", val, i);

}
}


main()
{
pthread_t tcb1, tcb2;

pthread_create(&tcb1, NULL, tcode1, NULL);
pthread_create(&tcb2, NULL, tcode2, NULL);

pthread_join(tcb1, NULL);
pthread_join(tcb2, NULL);
}

所以这是我的问题。

  1. 这些数据竞争发生在哪里(在我的代码中)?
  2. 我该如何修复它们?
4

2 回答 2

1

您有比赛,因为两个线程都访问相同的全局变量numOccupiedfirstOccupied. 您需要使用某种形式的锁定来同步对变量的访问。例如,您可以在执行添加/删除操作时使用信号量或互斥锁来锁定对共享全局状态的访问。

于 2012-04-13T23:43:04.773 回答
1

使用互斥锁来同步对共享数据结构的访问。您将需要以下内容:

pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);

作为基本原则,在读取/写入线程间共享的数据结构之前锁定互斥体,然后解锁。在这种情况下,Buffer加元数据numOccupiedfirstOccupied是您需要保护的共享数据结构。所以在buffadd()andbuffrem()中,一开始就锁定互斥量,最后解锁。并在main()启动线程前初始化互斥锁,加入后销毁。

于 2012-04-13T23:45:48.083 回答