一个变量只被一个线程读取,被另一个线程读取和写入,是否需要同步?
Does a variable only read by one thread, read and written by another, need synchronization?
动机:
我只是在学习多线程的基础知识,还没有接近完成它们,但我想在我的学习之旅的早期提出一个问题,以指导我找到与我正在工作的项目最相关的主题上。
主要:
一个。如果一个进程有两个线程,一个编辑一组变量,另一个只读取所述变量并且从不编辑它们的值;那么我们是否需要某种同步来保证读取线程读取值的有效性?
b。 OS 调度这两个线程是否有可能导致读取线程在写入线程写入同一内存位置的同时读取内存位置中的变量,或者这只是一个hardware/bus 永远不会允许这种情况发生,软件设计师永远不应该关心这种情况?如果变量是一个大结构而不是一个小的 int 或 char 怎么办?
a. If a process has two threads, one that edits a set of variables, the other only reads said variables and never edits their values; Then do we need any sort of synchronization for guaranteeing the validity of the read values by the reading thread?
一般来说,是。否则,编辑该值的线程只能在本地更改该值,这样其他线程将永远看不到该值的更改。这可能是因为编译器(可以使用 寄存器 到 read/store 变量)但也因为硬件(关于 缓存一致性 目标平台上使用的机制)。通常,锁、原子变量和内存屏障用于执行此类同步。
b. Is it possible for the OS scheduling these two threads to cause the reading-thread to read a variable in a memory location in the exact same moment while the writing-thread is writing into the same memory location, or that's just a hardware/bus situation will never be allowed happen and a software designer should never care about that? What if the variable is a large struct instead of a little int or char?
一般来说,不能保证访问是自动完成的。从理论上讲,两个执行一个线程的内核可以同时 load/store 同一个变量(但实际上通常不会)。它非常依赖于目标平台。
对于具有(一致的)缓存的处理器(即所有现代主流处理器)缓存行(即通常为 64 或 128 字节的块)对隐式有巨大影响线程之间的同步。这是一个复杂的主题,但您可以先阅读更多有关 cache coherence 的内容,以了解内存层次结构在现代平台上的工作方式。
缓存一致性协议防止两个 load/store 在同一缓存行中完全同时完成。如果变量跨越多个缓存行,则没有保护。
在广泛使用的 x86/x86-64 平台上,原始类型 <= 8 字节的变量 可以 进行原子修改(因为总线以及 DRAM 和缓存)假设地址正确对齐(它不跨越缓存行)。但是,这并不意味着所有此类访问都是原子的。您需要将此指定给 compiler/interpreter/etc。所以它 produces/executes 正确的指令。请注意,还有 16 字节原子的扩展。还有一个指令集扩展,用于支持 事务内存 。对于更广泛的类型(或可能是复合类型),您可能需要 lock 或 atomic state 来控制访问目标变量的原子性。
动机:
我只是在学习多线程的基础知识,还没有接近完成它们,但我想在我的学习之旅的早期提出一个问题,以指导我找到与我正在工作的项目最相关的主题上。
主要:
一个。如果一个进程有两个线程,一个编辑一组变量,另一个只读取所述变量并且从不编辑它们的值;那么我们是否需要某种同步来保证读取线程读取值的有效性?
b。 OS 调度这两个线程是否有可能导致读取线程在写入线程写入同一内存位置的同时读取内存位置中的变量,或者这只是一个hardware/bus 永远不会允许这种情况发生,软件设计师永远不应该关心这种情况?如果变量是一个大结构而不是一个小的 int 或 char 怎么办?
a. If a process has two threads, one that edits a set of variables, the other only reads said variables and never edits their values; Then do we need any sort of synchronization for guaranteeing the validity of the read values by the reading thread?
一般来说,是。否则,编辑该值的线程只能在本地更改该值,这样其他线程将永远看不到该值的更改。这可能是因为编译器(可以使用 寄存器 到 read/store 变量)但也因为硬件(关于 缓存一致性 目标平台上使用的机制)。通常,锁、原子变量和内存屏障用于执行此类同步。
b. Is it possible for the OS scheduling these two threads to cause the reading-thread to read a variable in a memory location in the exact same moment while the writing-thread is writing into the same memory location, or that's just a hardware/bus situation will never be allowed happen and a software designer should never care about that? What if the variable is a large struct instead of a little int or char?
一般来说,不能保证访问是自动完成的。从理论上讲,两个执行一个线程的内核可以同时 load/store 同一个变量(但实际上通常不会)。它非常依赖于目标平台。
对于具有(一致的)缓存的处理器(即所有现代主流处理器)缓存行(即通常为 64 或 128 字节的块)对隐式有巨大影响线程之间的同步。这是一个复杂的主题,但您可以先阅读更多有关 cache coherence 的内容,以了解内存层次结构在现代平台上的工作方式。 缓存一致性协议防止两个 load/store 在同一缓存行中完全同时完成。如果变量跨越多个缓存行,则没有保护。
在广泛使用的 x86/x86-64 平台上,原始类型 <= 8 字节的变量 可以 进行原子修改(因为总线以及 DRAM 和缓存)假设地址正确对齐(它不跨越缓存行)。但是,这并不意味着所有此类访问都是原子的。您需要将此指定给 compiler/interpreter/etc。所以它 produces/executes 正确的指令。请注意,还有 16 字节原子的扩展。还有一个指令集扩展,用于支持 事务内存 。对于更广泛的类型(或可能是复合类型),您可能需要 lock 或 atomic state 来控制访问目标变量的原子性。