先决条件—— 进程同步 锁变量为进程提供了最简单的同步机制。关于锁变量,值得注意的是-
- 这是一个 软件机制 以用户模式实现,即不需要操作系统的支持。
- 这是一个忙等待解决方案(即使在技术上等待的时候,也会让CPU忙)。
- 它可以用于两个以上的过程。
当Lock=0表示临界截面为空(初始值),Lock=1表示临界截面为已占用。 伪代码看起来像这样——
Entry section - while(lock != 0); Lock = 1;//critical sectionExit section - Lock = 0;
在下面的代码片段中可以看到用于进程同步的锁变量方法的更正式的方法:
C
char buffer[SIZE]; int count = 0, start = 0, end = 0; struct lock l; // initialize lock variable lock_init(&l); void put( char c) { // entry section lock_acquire(&l); // critical section begins while (count == SIZE) { lock_release(&l); lock_acquire(&l); } count++; buffer[start] = c; start++; if (start == SIZE) { start = 0; } // critical section ends // exit section lock_release(&l); } char get() { char c; // entry section lock_acquire(&l); // critical section begins while (count == 0) { lock_release(&l); lock_acquire(&l); } count--; c = buffer[end]; end++; if (end == SIZE) { end = 0; } // critical section ends // exit section lock_release(&l); return c; } |
在这里,我们可以看到读者-作者问题的经典实现。这里的缓冲区是共享内存,许多进程都在试图读取或写入一个字符。为了防止数据的任何模糊性,我们通过使用锁变量来限制并发访问。我们还对可以访问的读者/作者数量施加了限制。 现在,根据三个主要参数判断每个同步机制:
- 相互排斥。
- 进步
- 有界的等待。
其中互斥是最重要的 重要的 在所有参数中。在某些情况下,Lock变量不提供互斥。这一事实可以通过以下面给出的汇编语言代码的形式编写其伪代码得到最好的验证。
1. Load Lock, R0 ; (Store the value of Lock in Register R0.)2. CMP R0, #0 ; (Compare the value of register R0 with 0.)3. JNZ Step 1 ; (Jump to step 1 if value of R0 is not 0.)4. Store #1, Lock ; (Set new value of Lock as 1.)Enter critical section5. Store #0, Lock ; (Set the value of lock as 0 again.)
现在让我们假设进程P1和P2正在争夺关键部分,它们的执行顺序如下(Lock的初始值=0)——
- P1执行语句1并被抢占。
- P2执行语句1、2、3、4,进入临界段并被抢占。
- P1执行语句2、3、4,并进入临界段。
这里,过程P1的R0最初将锁值存储为0,但未能将锁值更新为1。因此,当P2执行时,它也会发现锁值为0,并通过将锁值设置为1进入临界区。但真正的问题是,当P1再次执行时,它不会检查Lock的更新值。它只检查R0中存储的前一个值,该值为0,并进入临界段。 这只是众多执行顺序中的一种。有些甚至可能提供相互排斥,但我们不能详细讨论这一点。根据墨菲定律“ 任何可能出错的事情都会出错 “.所以,像所有简单的事情一样,锁变量同步方法也有很多缺点,但对于我们开发更好的同步算法来解决我们在这里面临的问题来说,这是一个很好的起点。 本文由 西德尚巴贾杰2号 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。