无锁和无阻塞有什么区别?

时间:2009-07-28 12:40:59

标签: synchronization locking lock-free nonblocking

在数据结构同步的背景下,有人可以澄清“无锁”和“非阻塞”之间的区别吗?这些术语似乎可以被很多人互换使用,但我还不确定某个地方是否存在隐藏的细微差别。

我的意思是无锁是“没有锁”,非阻塞更像是保证进步。我怀疑一个暗示另一个而不是相反,我不确定。

欢迎参考。

5 个答案:

答案 0 :(得分:6)

锁定是一种访问控制机制。因此,我指的是当您想要对其进行独占访问时锁定资源。锁门,使用房间/做任何你想做的事情,现在为其他人解锁房间,以便他们现在可以使用它。当房间被锁定时,没有其他人可以进入房间,因此无法做任何事情。

阻止用于保证数据检索,除非你没有数据,否则不要回来。继续等待门/管道/插座(基本上是任何东西),当数据可用时,获取并返回。

Addition--
不要被词语的字面英语含义混淆,因为它们都可以在你试图将它们放入的上下文中交替使用。例如 - 锁定就像阻止让其他人使用相同的资源,阻止可以自行锁定(调用函数)到资源,直到数据可用。

所以LOCKING只是意味着您在指定的时间内捕获资源(除非您取消阻止它)。 并且,BLOCKING是您被阻止的,这意味着您无法继续,因为您没有数据,继续或继续。

实现它们的方式,通过更改进程的状态,等待中断或事件发生。

答案 1 :(得分:3)

他们完全不同。

锁定意味着您使用某种方法来使用锁来控制文件访问。这会阻止两个进程同时写入同一个文件,在另一个正在读取时停止一个写入,但允许两个进程同时读取。

阻止意味着该方法将在返回之前等待操作完成。

<强>更新

响应对示例的请求......如果我有时间,我会尝试添加示例,但是现在,这是对可能性的解释。

我们有3种方法可以执行锁定:

  • 阻止。如果锁定不可用,请等待。
  • 无阻塞。如果锁定不可用,则失败。

执行IO的两种方式:

  • 阻止。等到缓冲区准备就绪。
  • 无阻塞。如果我们不能立即读/写则失败

如果我们正常使用open()read(),我们会阻止IO。如果我们想要非阻塞IO,我们必须将O_NONBLOCK标记传递给open(),然后read()将返回E_AGAIN 而不是阻止。

默认情况下没有锁定。我们可以使用fcntl()F_SETLK致电F_SETLKW以获取锁定。如果锁不可用,前者会阻止,后者会因EACCESEAGAIN而失败。

我认为有两个可能的混淆点:

  • IO可以是阻塞/非阻塞,锁定可以是阻塞/非阻塞。
  • 除了数据尚未就绪之外,IO请求可以阻止,因为另一个进程已将文件锁定。

答案 2 :(得分:1)

是的,无锁意味着没有锁定机制。非阻塞意味着调用将立即返回,而不是等待发生某些外部事件(例如释放锁或缓冲区中的数据)。可以使用锁并使用非阻塞调用,例如在调用

flock(fh, LOCK_SH | LOCK_NB);

这意味着“试图获得一个读锁定,但如果你不能,请不要等待一个,立即返回并告诉我你不能”。没有LOCK_SH(“非阻塞”)的LOCK_NB(“共享锁定”)的默认行为是等待锁定可用性。

答案 3 :(得分:1)

它们可以相似,但经常在不同的环境中使用。在数据结构的上下文中,它们将是相同的。您也可以在IO的上下文中使用“非阻塞”,在这种情况下,它意味着函数不会在返回之前等待操作完成,或者操作肯定不会阻塞(例如,读取具有的数据)已被缓存)。

此外,非阻塞可能并不意味着某些东西是无锁的。例如,数据结构可能使用锁,但有一些不需要锁的非阻塞操作和其他需要锁的操作。

答案 4 :(得分:0)

通过一个例子的试探性答案:

使用两种方法wait()notify()来考虑一个对象(称为“事件”)。

  • 实施1:

    notify()以原子方式设置布尔值。 wait()循环,直到布尔值为true。两者都无锁,但wait() 阻止

  • 实施2:

    notify()获取锁定,设置布尔值然后释放锁定。 wait()获取锁定,读取布尔值,释放锁定,所有这些都在循环中,直到布尔值为真。因此,两者都基于锁定阻止

  • 实施3:

    最初锁定正在使用中。 notify()检查一个布尔值并释放锁定,如果它是真的。 wait()获取锁定并将布尔值设置为true。 notify() 非阻止(无论是无锁都可以证明)。 wait() 基于锁定阻止

所以我会说非阻塞意味着无锁,但它们并不等效,因为无锁操作仍然可以阻止某个条件在循环中。