在数据结构同步的背景下,有人可以澄清“无锁”和“非阻塞”之间的区别吗?这些术语似乎可以被很多人互换使用,但我还不确定某个地方是否存在隐藏的细微差别。
我的意思是无锁是“没有锁”,非阻塞更像是保证进步。我怀疑一个暗示另一个而不是相反,我不确定。
欢迎参考。
答案 0 :(得分:6)
锁定是一种访问控制机制。因此,我指的是当您想要对其进行独占访问时锁定资源。锁门,使用房间/做任何你想做的事情,现在为其他人解锁房间,以便他们现在可以使用它。当房间被锁定时,没有其他人可以进入房间,因此无法做任何事情。
阻止用于保证数据检索,除非你没有数据,否则不要回来。继续等待门/管道/插座(基本上是任何东西),当数据可用时,获取并返回。
Addition--
不要被词语的字面英语含义混淆,因为它们都可以在你试图将它们放入的上下文中交替使用。例如 - 锁定就像阻止让其他人使用相同的资源,阻止可以自行锁定(调用函数)到资源,直到数据可用。
所以LOCKING只是意味着您在指定的时间内捕获资源(除非您取消阻止它)。 并且,BLOCKING是您被阻止的,这意味着您无法继续,因为您没有数据,继续或继续。
实现它们的方式,通过更改进程的状态,等待中断或事件发生。
答案 1 :(得分:3)
他们完全不同。
锁定意味着您使用某种方法来使用锁来控制文件访问。这会阻止两个进程同时写入同一个文件,在另一个正在读取时停止一个写入,但允许两个进程同时读取。
阻止意味着该方法将在返回之前等待操作完成。
<强>更新强>
响应对示例的请求......如果我有时间,我会尝试添加示例,但是现在,这是对可能性的解释。
我们有3种方法可以执行锁定:
执行IO的两种方式:
如果我们正常使用open()
和read()
,我们会阻止IO。如果我们想要非阻塞IO,我们必须将O_NONBLOCK
标记传递给open()
,然后read()
将返回E_AGAIN
而不是阻止。
默认情况下没有锁定。我们可以使用fcntl()
或F_SETLK
致电F_SETLKW
以获取锁定。如果锁不可用,前者会阻止,后者会因EACCES
或EAGAIN
而失败。
我认为有两个可能的混淆点:
答案 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()
基于锁定,阻止。
所以我会说非阻塞意味着无锁,但它们并不等效,因为无锁操作仍然可以阻止某个条件在循环中。