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