C语言 我如何证明我需要一个互斥锁在这个代码?

i2loujxw  于 2022-12-17  发布在  其他
关注(0)|答案(1)|浏览(136)

我有一个非常简单的多线程程序,在这个程序中,我阅读一组数字,并最终将它们添加到全局sum中。我在每个线程中使用local_sum变量,然后将其添加到全局sum中。代码在最后给出。
问题是-我是否需要锁定thread_runner函数中的这行代码?

sum += local_sum;

我很确定我确实需要锁定它,但是程序总是给出正确的结果。如果我确实需要锁定,我如何证明这个实现是错误的?
注意:我只对互斥锁作为同步原语感兴趣。另外请忽略我没有检查返回值。
代码:

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void *thread_runner(void *index);
// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

long array[100000000];
long sum = 0;

int main() {
    /* Insert values in the array */
    long i = 0;
    for (i = 0; i < 100000000; i++) {
        array[i] = i+1;
    }

    /* Declare thread variables */
    pthread_t t1, t2, t3, t4;
    int index1 = 0;
    int index2 = 25000000;
    int index3 = 50000000;
    int index4 = 75000000;

    /* Create 4 threads */
    int rc = pthread_create(&t1, NULL, thread_runner, &index1);
    rc = pthread_create(&t2, NULL, thread_runner, &index2);
    rc = pthread_create(&t3, NULL, thread_runner, &index3);
    rc = pthread_create(&t4, NULL, thread_runner, &index4);

    /* Wait for threads to complete */
    rc = pthread_join(t1, NULL);
    rc = pthread_join(t2, NULL);
    rc = pthread_join(t3, NULL);
    rc = pthread_join(t4, NULL);

    printf("Sum: %ld\n", sum);

    return 0;
}

void *thread_runner(void *index) {
    int i = 0;
    int i_index = *((int*)index);
    long local_sum = 0;
    for (i = i_index; i < i_index+25000000; i++) {
        local_sum += array[i];
    }
    // Do i need to lock the following statement ?
    sum += local_sum;
}
fdbelqdn

fdbelqdn1#

我如何证明这个实现是错误?
你指向sum += local_sum行,然后说,“看!线程访问相同的共享变量,没有任何锁定,也没有任何其他形式的同步,”然后你指向语言规范中的部分,或者你指向some other suitable authority,它说“...未定义的行为”。
数据竞赛之所以糟糕,是因为它们是“不可预测的”。你不能依赖于一个包含数据竞赛的程序来给予正确的答案,也不能依赖于它来给出“错误的”答案。你不能依赖于测试来发现数据竞赛。

相关问题