我的 C 程序有三个线程
A
、B
和 C
,它们共享一些缓冲区。每个缓冲区都由互斥体保护,每个线程在写入/读取缓冲区之前必须锁定互斥体。
A
写入缓冲区,B
和 C
读取缓冲区。 main 函数创建 A
,等待直到用 pthread_mutex_lock()
锁定第一个缓冲区,然后创建 B
和 C
,以便缓冲区始终在读取之前写入。
#define mutex_lock(mutex, buff_num) log("wait on buff[%d]\n", buff_num); \
printf("pthread_mutex_lock returns %d\n", pthread_mutex_lock(mutex)); \
log("buff[%d] locked\n", buff_num)
#define mutex_unlock(mutex, buff_num) log("releasing buff[%d]\n", buff_num); \
pthread_mutex_unlock(mutex); \
log("buff[%d] released\n", buff_num)
...
typedef struct
{
pthread_mutex_t lock;
char data[MAX_DATA_LENGTH];
} buff_t;
uint8_t A_thread_ready = 0;
buff_t buff[NUM_BUFF];
...
int main()
{
...
for(int i=0; i<NUM_BUFF; i++)
{
if (pthread_mutex_init(&buff[i].lock, NULL) != 0)
{
pthread_exit(NULL);
}
}
...
status = pthread_create(&tid[0], NULL, &A_thread, NULL);
if ( 0 == status)
{
break;
}
do
{
nanosleep(&t1, &t2);
} while (0 == A_thread_ready);
status = pthread_create(&tid[1], NULL, &B_thread, NULL);
if ( 0 == status)
{
break;
}
...
}
...
extern uint8_t A_thread_ready;
extern buff_t buff[NUM_BUFF];
...
void* A_thread(void* arg)
{
uint8_t write_buff = 0;
...
mutex_lock(&buff_p->lock, write_buff);
buff_p = &(buff[write_buff]);
A_thread_ready = 1;
while(1)
{
...
mutex_unlock(&buff_p->lock, write_buff);
write_buff++;
write_buff %= NUM_BUFF;
mutex_lock(&buff_p->lock, write_buff);
buff_p = &(buff[write_buff]);
...
}
...
}
...
extern buff_t buff[NUM_BUFF];
...
void* B_thread(void* arg)
{
uint8_t read_buff = 0;
...
mutex_lock(&buff_p->lock, read_buff);
buff_p = &(buff[read_buff]);
while(1)
{
...
mutex_unlock(&buff_p->lock, read_buff);
read_buff++;
read_buff %= NUM_BUFF;
mutex_lock(&buff_p->lock, read_buff);
buff_p = &(buff[read_buff]);
...
}
...
}
但是,在运行程序时,从打印的日志来看,似乎在
A
锁定了一个缓冲区之后,B
能够锁定同一个缓冲区。
它做了一些事情,并释放了缓冲区。一段时间后
A
释放了这个缓冲区。我检查了每个pthread_mutex_lock()
调用的返回值,它总是0(成功)。我还应该检查什么来找出此问题的原因?
乍一看我对这段代码深感担忧:
pthread_mutex_lock(&buff_p->lock);
buff_p = &(buff[read_buff]);
while(1)
{
...
pthread_mutex_unlock(&buff_p->lock);
看起来确实像您锁定了存储在
buff_p->lock
(缓冲区1的锁)的结构中的某些互斥锁,然后您用buff_p
更改了buff_p = &(buff[read_buff]);
的值,然后解锁了其他一些互斥锁:互斥体位于
buff_p->lock
(缓冲区 2 的锁)。想必这些是完全不同的缓冲区上的不同锁。