为什么读取不是线程安全的?

问题描述 投票:0回答:4

我想知道为什么从内存中读取不是线程安全的。到目前为止我所看到的,尤其是this问题,从内存中读取似乎不是线程安全的。

我已经用 Python 编码了一段时间,现在开始使用 C++。我从来没有听说过Python中的阅读不是线程安全的。

如果我错了,请纠正我,但如果没有,请告诉我为什么从内存中读取不是线程安全的。

c++ thread-safety
4个回答
22
投票

读取是线程安全的,没有问题......直到有东西写入你正在读取的位置,然后......好吧,希望你能在数据更改之前读取,或者在数据更改之后读取(在这些情况下,不用担心),但有时,当你真的不想要它时,你会在写入过程中读取一半,然后你会得到完整的垃圾数据。

缓解这种情况的方法是确保您只在任何写入之前或之后进行读取,这需要您检查是否正在发生写入,从而使用某种同步锁。但这会让事情变慢,因为你显然是在检查锁,然后读取而不是读取。如果您正在使用原始数据类型(例如 int),那么您可以使用 CPU 同步来显着加快速度。

对于 Python,Python 数据很可能总是由语言运行时为您同步,如果不是,那么您迟早会遇到相同的线程读取问题。 (谷歌很快说是的,Python也会遇到同样的问题是你不小心)


9
投票

如果许多线程正在读取同一位置,直到没有人尝试写入该位置,则它是线程安全的。

考虑线程 A 是否正在读取某些内容,而线程 B 是否正在向正在读取的内存写入内容。它将生成一个

race condition
。每次启动时读取结果可能会变得无效或不同


9
投票

从内存中读取是线程安全的,但从可同时写入的内存中读取并不安全。

在 Python 中,这不是一个问题,因为许多对象是不可变的,因此在这些情况下仅修改引用,而不是内存本身。


1
投票

同时阅读同一内容 - 是安全的。 问题是当有东西同时写入时。

考虑以下代码:

int arr_len = 3;
int* arr = new int[arr_len];

void thread_1()
{
    std::cout << arr[arr_len-1];
}

void thread_2(int new_len)
{
    int* temp = new int[new_len];
    for(int i = 0; i < arr_len && i < new_len; ++i)
        temp[i] = arr[i];
    arr_len = new_len;
    delete arr;
    arr = temp;
}

假设

arr[arr_len]
是按顺序完成的(首先读取
arr_len
,然后读取
arr
)。

当 2 个线程交错运行时会发生什么? 可能会发生以下三种情况之一:

  • 没问题 - 你很幸运!
  • arr_len
    大于
    arr
    - UB :(
  • arr
    已失效(已删除)- UB :(
© www.soinside.com 2019 - 2024. All rights reserved.