考虑以下代码:
#define _XOPEN_SOURCE 600
#define _DEFAULT_SOURCE
#include <pthread.h>
#include <stdatomic.h>
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define ENTRY_NUM 100
struct value {
pthread_mutex_t mutex;
int i;
};
struct entry {
atomic_uintptr_t val;
};
struct entry entries[ENTRY_NUM];
void* thread1(void *arg)
{
for (int i = 0; i != ENTRY_NUM; ++i) {
struct value *val = (struct value*) atomic_load(&entries[i].val);
if (val == NULL)
continue;
pthread_mutex_lock(&val->mutex);
printf("%d\n", val->i);
pthread_mutex_unlock(&val->mutex);
}
return NULL;
}
void* thread2(void *arg)
{
/*
* Do some costy operations before continuing.
*/
usleep(1);
for (int i = 0; i != ENTRY_NUM; ++i) {
struct value *val = (struct value*) atomic_load(&entries[i].val);
pthread_mutex_lock(&val->mutex);
atomic_store(&entries[i].val, (uintptr_t) NULL);
pthread_mutex_unlock(&val->mutex);
pthread_mutex_destroy(&val->mutex);
free(val);
}
return NULL;
}
int main() {
for (int i = 0; i != ENTRY_NUM; ++i) {
struct value *val = malloc(sizeof(struct value));
pthread_mutex_init(&val->mutex, NULL);
val->i = i;
atomic_store(&entries[i].val, (uintptr_t) val);
}
pthread_t ids[2];
pthread_create(&ids[0], NULL, thread1, NULL);
pthread_create(&ids[1], NULL, thread2, NULL);
pthread_join(ids[0], NULL);
pthread_join(ids[1], NULL);
return 0;
}
假定在函数thread1中,加载了条目[i] .val,然后调度程序将进程调度为休眠。
然后线程2从usleep中唤醒,因为((struct val *)entry [0] .val)->互斥锁未锁定,thread2将其锁定,将NULL存储到entry [0] .val中并释放了条目的原始内容[ 0] .val。
现在,这是比赛条件吗?如果是这样,如何在不锁定条目或条目[0]的情况下避免这种情况?
您是正确的朋友,这种代码中确实存在竞争条件。