我在思考为什么从内存读取数据不是线程安全的。根据我所见,例如这个问题,从内存中读取数据似乎并不是线程安全的。
我已经使用Python编程了一段时间,现在开始学习C++。我从未听说过在Python中读取数据不是线程安全的。
如果我误解了,请纠正我,如果没有,请告诉我为什么从内存中读取数据不是线程安全的。
我在思考为什么从内存读取数据不是线程安全的。根据我所见,例如这个问题,从内存中读取数据似乎并不是线程安全的。
我已经使用Python编程了一段时间,现在开始学习C++。我从未听说过在Python中读取数据不是线程安全的。
如果我误解了,请纠正我,如果没有,请告诉我为什么从内存中读取数据不是线程安全的。
读取数据是线程安全的,没有问题......直到有些东西写入你正在读取的位置,然后......希望你在数据被更改之前或之后进行了读取(在这些情况下,没有问题),但有时候,就在你真的不想它发生的时候,你会读到写操作的一半,然后得到完全错误的数据。
缓解这种问题的方法是确保你只在写入之前或之后进行读取,这需要你检查是否正在进行写入,并使用某种同步锁。然而,这会使事情变慢,因为你显然要检查锁定,然后才能读取,而不是直接读取。如果你正在使用基本数据类型(例如int),那么你可以使用CPU同步来大大加速这个过程。
对于Python来说,很可能语言运行时已经为你同步了Python数据,如果没有,那么迟早会遇到相同的线程读取问题。(快速谷歌搜索表明,如果你不小心,Python也会出现相同的问题。)
如果多个线程正在读取相同的位置,只要没有人试图在那里写入,它就是线程安全的。
考虑一下如果线程A正在读取某些东西,同时线程B正在写入正在被读取的内存。这将产生“竞态条件”。读取结果可能会变得无效或每次启动时都不同。
从内存中读取数据是线程安全的,但是从同时可能被写入的内存中读取数据是不安全的。
在Python中,这个问题不太严重,因为许多对象都是不可变的,因此在这些情况下只有引用被修改,而不是内存本身。
同时阅读相同的内容是安全的。问题在于当有东西同时写入时。
考虑以下代码:
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
)。
当两个线程交替运行时会发生什么? 有三种可能:
arr_len
大于arr
- UB :(arr
无效(已删除)- UB :(