首页 > 解决方案 > 多个线程可以读取同一个类成员变量吗?

问题描述

多个线程可以在不创建竞争条件的情况下安全地读取同一个类成员变量吗?

class foo {
    int x;
};

void Thread1(foo* bar) {
    float j = bar->x * 5;
}

void Thread2(foo* bar) {
    float k = bar->x / 5;
}

因此,例如,如果我们有两个线程正在运行Thread1,并且Thread2. 如果每个线程都传递同一个 foo对象,它们是否可以独立运行,没有竞争条件,因为我们只读取变量而不写入?还是访问对象的行为使整个事情变得不安全?

如果上面安全的,第三个线程可以安全地写入同一个foo对象,只要它不接触foo::x

#include <thread>

class foo {
public:
    int x = 1;
    int y = 1;
};

void Thread1(foo* bar) {
    int j;
    for (int i = 0; i < 1000; i++) {
        j = bar->x * 5;
    }
    printf("T1 - %i\n", j);
}

void Thread2(foo* bar) {
    int k;
    for (int i = 0; i < 1000; i++) {
        k = bar->x / 5;
    }
    printf("T2 - %i\n", k);
}

void Thread3(foo* bar) {
    for (int i = 0; i < 1000; i++) {
        bar->y += 3;
    }
    printf("T3 - %i\n", bar->y);
}

int main() {
    foo bar;

    std::thread t1(Thread1, &bar);
    std::thread t2(Thread2, &bar);
    std::thread t3(Thread3, &bar);

    t1.join();
    t2.join();
    t3.join();

    printf("x %i, y %i\n", bar.x, bar.y);

    return 0;
}

标签: c++thread-safety

解决方案


多个线程可以在不创建竞争条件的情况下安全地读取同一个类成员变量吗?

是和不是。

的 - 您提供的代码不会导致竞争条件,因为当您有至少 2 个线程在同一共享资源上工作并且其中至少一个线程正在写入该资源时,可能会发生竞争条件。

- 您的代码不被认为是线程安全的,因为它公开了 x 和 y 成员以供读写,并使得(对于您或使用您的代码的其他程序员)可能导致竞争条件。您依赖于您的知识(随着时间的推移您可能会忘记) x 应该只被读取,而不是写入,并且 y 应该只由单个线程写入。您应该通过在关键代码部分中创建互斥来强制执行此操作。

如果您希望线程仅从 x 和 y 读取,则应使此类immutable


推荐阅读