这种情况是否被视为比赛条件?

问题描述 投票:1回答:1

考虑以下代码:

#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]的情况下避免这种情况?

c multithreading locking atomic race-condition
1个回答
2
投票

您是正确的朋友,这种代码中确实存在竞争条件。

© www.soinside.com 2019 - 2024. All rights reserved.