多个线程可以读取同一个类成员变量吗?

KKl*_*zal 2 c++ thread-safety

多个线程可以安全地读取同一个类成员变量而不产生竞争条件吗?

class foo {
    int x;
};

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

void Thread2(foo* bar) {
    float k = bar->x / 5;
}
Run Code Online (Sandbox Code Playgroud)

因此,例如,如果我们有两个线程正在运行,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;
}
Run Code Online (Sandbox Code Playgroud)

Sub*_*ine 6

多个线程可以安全地读取同一个类成员变量而不产生竞争条件吗?

是和否。

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

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

如果您希望线程仅从 x 和 y 读取,您应该使此类不可变