刚观看了一个关于信号量的视频,并尝试挖掘更多信息。不太确定信号量在汇编级别上是如何工作的。
P(s):
s = s - 1
if (s < 0) {wait on s}
CRITICAL SECTION
V(s):
s = s + 1
if(threads are waiting on s) {wake one}
我理解这些功能背后的概念是什么,但是我无法解决这个问题。
说S = 1 你有2个主题:主题1和主题2
Thread One Thread Two
load s load s
subtract s,1 subtract s,1
save s save s
然后在减法和保存之间有一个上下文切换,两个设置s都设置为0。两个线程都不会将s视为0进入临界区。我不确定一个线程如何在汇编级别进行上下文切换时变为独占,这样两者都可以看到s = 0.。
答案 0 :(得分:2)
关键是增量和减量以某种方式使用原子指令。在x86中,有一种形式的add指令,它与锁定前缀相结合,允许你以原子方式对内存位置进行添加。因为它是单个指令,所以在执行期间不会发生上下文切换,并且锁前缀意味着CPU确保在增量期间不会发生其他访问。
如果原子添加不可用,则还有其他选项。一个常见的是原子比较和交换指令。在大多数支持并行或并发代码的系统上找到它,它是一个带有两个值的指令,旧的和新的,如果内存位置等于旧的,则将其设置为新值。这可以在循环中用于实现原子添加:
l:
load r0 s
mov r1 r0
add r0 -1
cas s r1 r0
jmpf l
这会加载一个值,然后从值的副本中减去1。然后我们尝试存储较低的值,但如果它已经改变,我们就会失败,然后重新开始。