2017-04-12 107 views
0

刚刚观看了一个关于信号量的视频,并试图挖掘更多信息。不太清楚信号灯如何在组件级别上工作。不理解信号量低层

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

您忘记了故障中的“等待”部分。 –

+0

不确定你的意思? S上有一个互斥量吗? – train55255

+0

不,不是互斥体,而是信号量。它是一种不同的同步机制,但就像互斥体一样,它通常提供高效*阻塞*,即它与OS调度程序交互。 –

回答

2

关键是增量和减量使用原子指令。在x86中,有一种添加指令的形式,它与锁前缀结合使用,可以以原子方式执行对内存位置的添加。由于它是单个指令,因此在执行过程中不会发生上下文切换,并且锁定前缀意味着CPU确保在增量过程中不会出现其他任何访问。

如果原子添加不可用,那么还有其他选项。一个常见的是原子比较和交换指令。在大多数支持并行或并发代码的系统上发现,它是一个指令,它带有两个值,一个是旧的,一个是新的,如果内存位置等于旧的,则将其设置为新值。这可以在循环中用于实现原子添加:

l: 
load r0 s 
mov r1 r0 
add r0 -1 
cas s r1 r0 
jmpf l 

这会加载一个值,然后从该值的副本中减去1。然后我们尝试存储较低的值,但如果它发生了变化,我们将失败并重新开始。

+0

非常感谢你,我隐约记得我的教授说,在讲座中,这些指示是原子性的,但是你只是清除了所有这些,并把它打在头上。非常感谢! – train55255

+0

希望我的教授能多走一步,再深入一点,再次感谢你。但是,这不会变得低效。说一下,如果有很多上下文切换,你是否会遇到试图添加或减少的四条指令? – train55255