示例: 线程完成对共享变量的写入,然后解锁它,但继续使用该变量的值(不更改它(。 立即,另一个线程成功解锁((互斥锁并读取共享变量。
对于我的(错误(理解,在这种情况下可能会发生一些事情:
在 WRITER 线程上:
-
编译器优化可能仅在以后的某个时间点进行写入
-
写入的值可以保留在当前 CPU 内核的缓存中,并在以后的某个时间点刷新到内存中。
在读取器线程上:
-
变量的值可能在互斥锁((之前被读取,并且由于某些编译器优化或只是CPU缓存的常规工作,仍然被视为"已经从内存中读取",因此不会再次从内存中获取。
-
因此,我们在这里的值不是来自另一个线程的更新值。
pthread 互斥锁/unlock(( 函数是否执行任何代码将当前缓存"刷新"到内存以及确保当前线程与其他所有内容同步所需的任何其他内容(我想不出除了缓存之外的任何东西(,还是只是不需要(至少在所有已知架构中(?
因为如果所有互斥体所做的只是名称所做的 - 相互排斥它的引用 - 那么,如果我有数千个线程处理相同的数据,并且从我的算法的角度来看,我已经知道当一个线程使用变量时,没有其他线程会同时尝试使用它, 而不是这意味着我不需要互斥锁?或者我的代码会缺少一些在 PTHREAD 库中实现的低级和特定于体系结构的方法以避免上述问题?
pthreads 互斥锁和解锁函数在 POSIX 中的函数列表中"...同步线程执行,并同步相对于其他线程的内存"。所以,是的,它们所做的不仅仅是联锁执行。
它们是否需要向硬件发出额外的指令当然取决于架构(注意,除非另有说明,否则几乎每个现代 CPU 架构至少会愉快地重新排序读取(,但在每种情况下,这些函数都必须充当"编译器屏障"——也就是说,它们确保编译器不会重新排序, 在允许的情况下合并或省略内存访问。
允许多个线程读取共享值而不相互排斥 - 您只需要确保写入线程和读取线程都在写入和读取之间执行了一些同步功能。 例如,允许的情况是,有许多读取线程延迟读取共享状态,直到它们通过屏障(pthread_barrier_wait()
(,并且有一个写入线程在通过屏障之前执行其对共享状态的所有写入。 读写器锁(pthread_rwlock_*
(也是围绕这个想法建立的。