无锁和非阻塞有什么区别?
在数据结构同步的背景下,有人可以澄清“无锁”和“非阻塞”之间的区别吗? 这些术语似乎被很多人互换使用,但我还不确定是否在某处隐藏着一些微妙的差异。
我的意思是无锁是“没有锁”,而非阻塞更像是保证进度。 我怀疑一个暗示另一个,但不是相反,我不确定。
欢迎参考。
In the context of data-structures synchronization, can someone clarify the difference between "lockless" and "non-blocking"? These terms seem to be used interchangeably by a lot of people but I'm not yet sure if there isn't some subtle difference hidden somewhere.
I mean lockless is "without locks" and non-blocking is more like guaranteeing progress. I suspect that one implies the other but not the other way around, I'm not sure.
References welcome.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
它们可能相似,但经常在不同的上下文中使用。 在数据结构的上下文中,它们是同一件事。 您还可以在 IO 上下文中使用“非阻塞”,在这种情况下,这意味着函数在返回之前不会等待操作完成,或者操作肯定不会阻塞(例如,读取具有已经被缓存了)。
此外,非阻塞可能并不意味着某些东西是无锁的。 例如,数据结构可能使用锁,但有一些不需要锁的非阻塞操作和其他需要锁的阻塞操作。
They can be similar, but often used in different contexts. In the context of a data structure, they would be the same thing. You could also use "non-blocking" in the context of IO as well, in which case it means that the function will not wait for the operation to complete before returning or that the operation is certain not to block (e.g. reading data that has already been cached).
Also, non-blocking may not imply that something is lockless. For example, a data structure may use locks but have some non-blocking operations that don't require a lock and other blocking operations that do require one.
是的,无锁意味着没有锁定机制。 非阻塞意味着调用将立即返回,而不是等待某些外部事件(例如锁的释放或数据到达缓冲区)发生。 可以拥有锁并使用非阻塞调用,例如在调用中,
这意味着“尝试获取读锁,但如果不能,请不要等待,立即返回并告诉我你可以't"。 没有
LOCK_NB
(“非阻塞”)的LOCK_SH
(“共享锁”)的默认行为是等待锁可用。Yes, lockless means without a locking mechanism. Non-blocking means that a call is going to return immediately rather than waiting for some external event (such as the release of a lock, or data arriving in a buffer) to occur. It's possible to have locks and use non-blocking calls, as for instance in the call
which means "try to get a read lock, but if you can't, don't wait around for one, return immediately and tell me you couldn't". The default behavior of
LOCK_SH
("shared lock") withoutLOCK_NB
("non-blocking") would be to wait for lock availability.他们完全不同。
锁定意味着您使用某种方法通过锁来控制文件访问。 这会阻止两个进程同时写入同一个文件,在另一个进程正在读取时停止一个写入,但允许两个进程同时读取。
阻塞意味着该方法将等待操作完成后再返回。
更新
为了响应示例请求...如果有时间,我会尝试添加示例,但现在,这里是对可能性的解释。
我们有 3 种方法来执行锁定:
以及执行 IO 的 2 种方式:
如果我们正常使用
open()
和read()
,我们会遇到阻塞 IO。 如果我们想要非阻塞 IO,我们必须将O_NONBLOCK
标志传递给open()
,然后read()
将返回E_AGAIN
而不是阻塞。
默认情况下没有锁定。 我们可以使用
F_SETLK
或F_SETLKW
调用fcntl()
来获取锁。 如果锁不可用,前者会阻塞,后者会失败并返回EACCES
或EAGAIN
。我认为有两个可能的混淆点:
They're totally different.
Locking means you use some method to control file access using locks. This stops two processes writing to the same file at the same time, stops one writing while another is reading, but allows two to read at the same time.
Blocking means the method will wait for the operation to complete before returning.
Update
In response to the request for examples... I will try to add examples if I get time, but for now, here's an explanation of the possibilities.
We have 3 ways to perform locking:
And 2 ways to perform IO:
If we use
open()
andread()
as normal, we get blocking IO. If we want non-blocking IO we have to pass theO_NONBLOCK
flag toopen()
, andread()
will then returnE_AGAIN
instead of blocking.
By default there is no locking. We can call
fcntl()
withF_SETLK
orF_SETLKW
to obtain the lock. The former blocks if the lock is unavailable, the latter fails withEACCES
orEAGAIN
.I think there are two possible points of confusion:
锁定是一种访问控制机制。 我的意思是,当您想要独占访问某个资源时,您会锁定该资源。 锁上门,使用房间/做任何你想做的事,现在为其他人解锁房间,以便他们现在可以使用它。 当房间被锁上时,其他人无法进入房间,因此无法做任何事情。
阻塞用于保证数据检索,除非您没有数据,否则不会回来。 继续在门/管道/插座(基本上是任何东西)处等待,当数据可用时获取并返回。
加法--
不要对这些单词的字面英语含义感到困惑,因为它们都可以在您尝试放入它们的上下文中互换使用。例如 - 锁定 就像 阻塞其他人使用相同的资源,阻塞可以锁定您自己(调用函数)到该资源,直到数据可用。
所以锁定只是意味着您在指定的时间内捕获资源(除非您取消阻止它)。
并且,BLOCKING 是您被阻止,这意味着您无法继续进行,因为您没有数据、继续或继续。
它们的实现方式是通过更改进程的状态并等待中断或事件发生。
Locking is an access control mechanism. Whereby i mean you lock a resource when you want an exclusive access to it. Lock the door, use the room/do whatever you wish, now unlock the room for others, so that they can use it now. While the room is locked, no one else could have entered the room, thus could not have done anything.
Blocking is used for guaranteed data-retrieval, that unless you dont have data, dont come back. Keep waiting at the door/pipe/socket(basically anything) and when data is available get it and come back.
Addition--
Do not get confused by the literal english-meaning of the words, as they both can be used interchange-ably in the context you try to put them in. For example -- locking is like blocking for others to use the same resource, and blocking can be locking yourself(calling function) to the resource until data is available.
So LOCKING simply mean you capturing a resource for a specified amount time(unless you un-block it).
And, BLOCKING is you are blocked, which means you cannot proceed further as you do not have data, to proceed or go ahead.
The way they are implemented, by changing the states of the process, and waiting for the interrupt or event to occur.
通过示例给出初步答案:
考虑一个具有两个方法的对象(称为“事件”):
wait()
和notify()
。实现1:
notify()
以原子方式设置一个布尔值。wait()
循环直到布尔值为 true。 两者都是无锁,但wait()
是阻塞。实施2:
notify()
获取锁,设置布尔值,然后释放锁。wait()
获取锁、读取布尔值、释放锁,所有这些都在一个循环中,直到布尔值为 true。 因此,两者都是基于锁、阻塞。实施3:
最初锁正在使用中。
notify()
检查一个布尔值,如果为真则释放锁。wait()
获取锁并将布尔值设置为 true。notify()
是非阻塞(是否是无锁是有争议的)。wait()
是基于锁、阻塞的。所以我想说,非阻塞意味着无锁,但它们并不等同,因为无锁操作仍然可以阻塞循环中的条件。
A tentative answer through an example:
Consider an object (called "event") with two methods,
wait()
andnotify()
.Implementation 1:
notify()
atomically sets a boolean.wait()
loops until the boolean is true. Both are lockless, butwait()
is blocking.Implementation 2:
notify()
gets a lock, sets a boolean then releases the lock.wait()
gets the lock, reads the boolean, releases the lock, all this in a loop until the boolean is true. Both are thus lock-based, blocking.Implementation 3:
Initially the lock is in use.
notify()
checks a boolean and releases the lock if it's true.wait()
gets the lock and sets the boolean to true.notify()
is non-blocking (it is argueable whether it is lockless or not).wait()
is lock-based, blocking.So I would say that non-blocking implies lockless, but they are not equivalent because a lockless operation can still block for a condition in a loop.