在数据结构同步的上下文中,有人可以澄清“无锁”和“非阻塞”之间的区别吗?这些术语似乎被很多人互换使用,但我还不确定是否在某处隐藏了一些细微的差异。
我的意思是无锁是“没有锁”,非阻塞更像是保证进度。我怀疑一个暗示另一个,但不是相反,我不确定。
欢迎参考。
在数据结构同步的上下文中,有人可以澄清“无锁”和“非阻塞”之间的区别吗?这些术语似乎被很多人互换使用,但我还不确定是否在某处隐藏了一些细微的差异。
我的意思是无锁是“没有锁”,非阻塞更像是保证进度。我怀疑一个暗示另一个,但不是相反,我不确定。
欢迎参考。
锁定是一种访问控制机制。我的意思是当您想要独占访问资源时锁定资源。锁门,使用房间/随心所欲,现在为其他人解锁房间,以便他们现在可以使用。当房间被锁住时,没有其他人可以进入房间,因此无法做任何事情。
阻塞用于保证数据检索,除非你没有数据,否则不要回来。继续在门口/管道/插座(基本上任何东西)等待,当数据可用时获取并返回。
加法
——不要被单词的字面英文意思混淆,因为它们都可以在你尝试放入它们的上下文中互换使用。例如——锁定就像阻止其他人使用它们一样资源,并且阻塞可以将自己(调用函数)锁定到资源,直到数据可用。
所以锁定只是意味着你在指定的时间内捕获资源(除非你取消阻止它)。而且,BLOCKING 是您被阻止,这意味着您无法继续进行,因为您没有数据,继续或继续。
它们的实现方式,通过改变进程的状态,并等待中断或事件发生。
他们完全不同。
锁定意味着您使用某种方法来使用锁定来控制文件访问。这会停止两个进程同时写入同一个文件,在另一个正在读取时停止一个写入,但允许两个进程同时读取。
阻塞意味着该方法将在返回之前等待操作完成。
更新
响应示例请求...如果有时间,我将尝试添加示例,但是现在,这里是对可能性的解释。
我们有 3 种方法来执行锁定:
以及 2 种执行 IO 的方法:
如果我们像往常一样使用open()
and read()
,我们会得到阻塞 IO。如果我们想要非阻塞 IO,我们必须将O_NONBLOCK
标志传递给open()
,然后read()
将返回E_AGAIN
而不是阻塞。
默认情况下没有锁定。我们可以调用fcntl()
with F_SETLK
orF_SETLKW
来获取锁。如果锁不可用,前者会阻塞,后者会以EACCES
or失败EAGAIN
。
我认为有两个可能的混淆点:
是的,无锁意味着没有锁定机制。非阻塞意味着调用将立即返回,而不是等待某些外部事件(例如释放锁或数据到达缓冲区)发生。可以有锁并使用非阻塞调用,例如在调用中
flock(fh, LOCK_SH | LOCK_NB);
这意味着“尝试获得一个读锁,但如果你不能,不要等待一个,立即返回并告诉我你不能”。LOCK_SH
没有 ("non-blocking") 的 ("shared lock")的默认行为LOCK_NB
是等待锁的可用性。
它们可以相似,但通常用于不同的上下文。在数据结构的上下文中,它们将是同一件事。您也可以在 IO 的上下文中使用“非阻塞”,在这种情况下,这意味着函数在返回之前不会等待操作完成,或者操作肯定不会阻塞(例如读取具有已经被缓存)。
此外,非阻塞可能并不意味着某些东西是无锁的。例如,一个数据结构可能使用锁,但有一些不需要锁的非阻塞操作和其他需要锁的阻塞操作。
通过一个例子试探性的回答:
考虑一个具有两种方法的对象(称为“事件”),wait()
并且notify()
.
实施1:
notify()
原子地设置一个布尔值。wait()
循环直到布尔值为真。两者都是无锁的,但wait()
都是阻塞的。
实施2:
notify()
获得一个锁,设置一个布尔值然后释放锁。wait()
获取锁,读取布尔值,释放锁,所有这些都在一个循环中,直到布尔值为真。因此,两者都是基于锁的,阻塞的。
实施3:
最初,锁正在使用中。notify()
检查一个布尔值,如果为真则释放锁。wait()
获取锁并将布尔值设置为 true。notify()
是非阻塞的(它是否无锁是有争议的)。wait()
是基于锁的,阻塞的。
所以我会说非阻塞意味着无锁,但它们并不等价,因为无锁操作仍然可以阻塞循环中的条件。