死锁和活锁有什么区别?
有人可以用示例(代码)解释一下死锁和活锁之间的区别吗?
Can somebody please explain with examples (of code) what is the difference between deadlock and livelock?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
摘自http://en.wikipedia.org/wiki/Deadlock:
Taken from http://en.wikipedia.org/wiki/Deadlock:
活锁
活锁和死锁之间的主要区别是线程不会被阻塞,相反,它们会尝试不断地相互响应。
在此图像中,两个圆圈(线程或进程)将尝试通过左右移动为另一个圆圈提供空间。但他们不能再进一步了。
Livelock
The main difference between livelock and deadlock is that threads are not going to be blocked, instead they will try to respond to each other continuously.
In this image, both circles (threads or processes) will try to give space to the other by moving left and right. But they can't move any further.
这里的所有内容和示例均来自
操作系统:内部结构和设计原则
威廉·斯托林斯
8° 版
死锁:两个或多个进程无法继续进行的情况,因为每个进程都在等待另一个进程执行某项操作。
例如,考虑两个进程 P1 和 P2,以及两个资源 R1 和 R2。假设每个进程都需要访问这两种资源来执行其部分功能。那么可能会出现以下情况:OS将R1分配给P2,将R2分配给P1。每个进程都在等待这两个资源之一。两者都不会释放它已经拥有的资源,直到它获得为止
另一个资源并执行需要这两个资源的功能。两人
进程死锁
活锁:两个或多个进程不断改变其状态以响应其他进程的变化而不做任何有用的工作的情况:
饥饿:调度程序无限期地忽略可运行进程的情况;尽管它能够进行,但它从未被选择。
假设三个进程(P1、P2、P3)各自需要定期访问资源 R。考虑这样的情况:P1 拥有该资源,而 P2 和 P3 都被延迟,等待该资源。当 P1 退出其关键部分时,应允许 P2 或 P3 访问 R。假设操作系统授予对 P3 的访问权限,并且在 P3 完成其关键部分之前 P1 再次需要访问。如果操作系统在 P3 完成后授予对 P1 的访问权限,随后交替授予对 P1 和 P3 的访问权限,则即使不存在死锁情况,也可能无限期地拒绝 P2 对资源的访问。
附录 A - 并发主题
死锁示例
如果两个进程在执行 while 语句之前将其标志设置为 true,则每个进程都会认为对方已进入其临界区,造成僵局。
活锁示例
[...]考虑以下事件序列:
该序列可以无限期地延长,并且两个进程都不能进入其临界区。严格来说,这不是死锁,因为两个进程相对速度的任何改变都会打破这个循环并允许进入临界区。这种情况称为活锁。回想一下,当一组进程希望进入其临界区但没有进程能够成功时,就会发生死锁。使用活锁,可能存在成功的执行序列,但也可以描述一个或多个没有进程进入其临界区的执行序列。
不再满足于书本。
那么自旋锁呢?
自旋锁是一种避免操作系统锁定机制成本的技术。通常您会这样做:
当
beginLock()
的成本远高于doSomething()
时,问题就开始出现。用非常夸张的话说,想象一下当beginLock
花费 1 秒,但doSomething
只花费 1 毫秒时会发生什么。在这种情况下,如果你等待 1 毫秒,你就可以避免受到 1 秒的阻碍。
为什么
beginLock
会花费这么多?如果锁是免费的,则不会花费很多(请参阅https://stackoverflow.com/a/49712993/5397116 ),但如果锁未释放,操作系统将“冻结”您的线程,设置一种机制在锁释放时唤醒您,然后在将来再次唤醒您。所有这些都比一些检查锁的循环要昂贵得多。这就是为什么有时最好使用“自旋锁”。
例如:
如果您的实现不小心,您可能会遇到活锁,将所有 CPU 都花在锁机制上。
另请参阅:
https://preshing.com/20120226/roll-your-own -轻量级互斥体/
我的自旋锁实现是否正确且最佳?
摘要:
死锁:没有人进步、什么都不做的情况(睡觉、等待等)。 CPU使用率会很低;
活锁:没有人进步的情况,但是CPU花费在锁定机制上而不是在你的计算上;
饥饿:一个进程永远没有机会运行的情况;由于纯粹的运气不佳或由于其某些属性(例如低优先级);
自旋锁:避免等待锁释放的成本的技术。
All the content and examples here are from
Operating Systems: Internals and Design Principles
William Stallings
8º Edition
Deadlock: A situation in which two or more processes are unable to proceed because each is waiting for one the others to do something.
For example, consider two processes, P1 and P2, and two resources, R1 and R2. Suppose that each process needs access to both resources to perform part of its function. Then it is possible to have the following situation: the OS assigns R1 to P2, and R2 to P1. Each process is waiting for one of the two resources. Neither will release the resource that it already owns until it has acquired
the other resource and performed the function requiring both resources. The two
processes are deadlocked
Livelock: A situation in which two or more processes continuously change their states in response to changes in the other process(es) without doing any useful work:
Starvation: A situation in which a runnable process is overlooked indefinitely by the scheduler; although it is able to proceed, it is never chosen.
Suppose that three processes (P1, P2, P3) each require periodic access to resource R. Consider the situation in which P1 is in possession of the resource, and both P2 and P3 are delayed, waiting for that resource. When P1 exits its critical section, either P2 or P3 should be allowed access to R. Assume that the OS grants access to P3 and that P1 again requires access before P3 completes its critical section. If the OS grants access to P1 after P3 has finished, and subsequently alternately grants access to P1 and P3, then P2 may indefinitely be denied access to the resource, even though there is no deadlock situation.
APPENDIX A - TOPICS IN CONCURRENCY
Deadlock Example
If both processes set their flags to true before either has executed the while statement, then each will think that the other has entered its critical section, causing deadlock.
Livelock Example
[...] consider the following sequence of events:
This sequence could be extended indefinitely, and neither process could enter its critical section. Strictly speaking, this is not deadlock, because any alteration in the relative speed of the two processes will break this cycle and allow one to enter the critical section. This condition is referred to as livelock. Recall that deadlock occurs when a set of processes wishes to enter their critical sections but no process can succeed. With livelock, there are possible sequences of executions that succeed, but it is also possible to describe one or more execution sequences in which no process ever enters its critical section.
Not content from the book anymore.
And what about spinlocks?
Spinlock is a technique to avoid the cost of the OS lock mechanism. Typically you would do:
A problem start to appear when
beginLock()
costs much more thandoSomething()
. In very exagerated terms, imagine what happens when thebeginLock
costs 1 second, butdoSomething
cost just 1 millisecond.In this case if you waited 1 millisecond, you would avoid being hindered for 1 second.
Why the
beginLock
would cost so much? If the lock is free is does not cost a lot (see https://stackoverflow.com/a/49712993/5397116), but if the lock is not free the OS will "freeze" your thread, setup a mechanism to wake you when the lock is freed, and then wake you again in the future.All of this is much more expensive than some loops checking the lock. That is why sometimes is better to do a "spinlock".
For example:
If your implementation is not careful, you can fall on livelock, spending all CPU on the lock mechanism.
Also see:
https://preshing.com/20120226/roll-your-own-lightweight-mutex/
Is my spin lock implementation correct and optimal?
Summary:
Deadlock: situation where nobody progress, doing nothing (sleeping, waiting etc..). CPU usage will be low;
Livelock: situation where nobody progress, but CPU is spent on the lock mechanism and not on your calculation;
Starvation: situation where one procress never gets the chance to run; by pure bad luck or by some of its property (low priority, for example);
Spinlock: technique of avoiding the cost waiting the lock to be freed.
死锁
死锁是任务等待的一种情况
无限期地满足永远无法实现的条件
使满意
- 任务要求对共享的独占控制
资源
- 任务在等待其他任务时保留资源
待释放资源
- 任务不能被迫放弃资源
- 存在循环等待条件
LIVELOCK
当两个或
更多任务依赖并使用一些
导致循环依赖的资源
这些任务继续进行的条件
永远运行,从而阻塞所有较低的
运行优先级任务(这些
较低优先级的任务遇到某种情况
称为饥饿)
DEADLOCK
Deadlock is a condition in which a task waits
indefinitely for conditions that can never be
satisfied
- task claims exclusive control over shared
resources
- task holds resources while waiting for other
resources to be released
- tasks cannot be forced to relinguish resources
- a circular waiting condition exists
LIVELOCK
Livelock conditions can arise when two or
more tasks depend on and use the some
resource causing a circular dependency
condition where those tasks continue
running forever, thus blocking all lower
priority level tasks from running (these
lower priority tasks experience a condition
called starvation)
也许这两个示例向您说明了死锁和活锁之间的区别:
死锁的 Java 示例:
示例输出:
活锁的 Java 示例:
示例输出:
这两个示例都强制线程以不同的顺序获取锁。
当死锁等待另一个锁时,
活锁并不真正等待——它拼命地尝试获取锁,但没有机会获得它。每次尝试都会消耗 CPU 周期。
Maybe these two examples illustrate you the difference between a deadlock and a livelock:
Java-Example for a deadlock:
Sample output:
Java-Example for a livelock:
Sample output:
Both examples force the threads to aquire the locks in different orders.
While the deadlock waits for the other lock,
the livelock does not really wait - it desperately tries to acquire the lock without the chance of getting it. Every try consumes CPU cycles.
想象一下,您有线程 A 和线程 B。它们在同一个对象上
同步
,并且在该块内有一个它们都在更新的全局变量;因此,当线程 A 进入
while
循环并持有锁时,它会执行其必须执行的操作,并将commonVar
设置为true
。然后线程B进来,进入while
循环,由于commonVar
现在是true
,它能够持有锁。它这样做,执行synchronized
块,并将commonVar
设置回false
。现在,线程 A 再次获取新的 CPU 窗口,它原本即将退出while
循环,但线程 B 刚刚将其设置回false
,因此循环再次重复。线程会做一些事情(因此它们不会被传统意义上的阻塞),但几乎什么也不做。也许还值得一提的是,活锁不一定必须出现在这里。我假设一旦同步块完成执行,调度程序就会优先考虑另一个线程。大多数时候,我认为这是一个很难实现的期望,并且取决于幕后发生的许多事情。
Imagine you've thread A and thread B. They are both
synchronised
on the same object and inside this block there's a global variable they are both updating;So, when thread A enters in the
while
loop and holds the lock, it does what it has to do and set thecommonVar
totrue
. Then thread B comes in, enters in thewhile
loop and sincecommonVar
istrue
now, it is be able to hold the lock. It does so, executes thesynchronised
block, and setscommonVar
back tofalse
. Now, thread A again gets it's new CPU window, it was about to quit thewhile
loop but thread B has just set it back tofalse
, so the cycle repeats over again. Threads do something (so they're not blocked in the traditional sense) but for pretty much nothing.It maybe also nice to mention that livelock does not necessarily have to appear here. I'm assuming that the scheduler favours the other thread once the
synchronised
block finish executing. Most of the time, I think it's a hard-to-hit expectation and depends on many things happening under the hood.我只是想分享一些知识。
死锁
如果一组线程/进程中的每个线程/进程都在等待只有该组中的另一个进程才能引发的事件,则一组线程/进程将陷入死锁。
这里重要的是另一个进程也在同一组中。这意味着另一个进程也被阻止,没有人可以继续。
当进程被授予对资源的独占访问权限时,就会发生死锁。
必须满足这四个条件才会发生死锁。
如果我们发现这些条件,那么我们可以说可能会发生像死锁这样的情况。
LiveLock
每个线程/进程都一次又一次地重复相同的状态,但不会进一步前进。类似于死锁,因为进程无法进入临界区。然而,在死锁中,进程等待而不执行任何操作,但在活锁中,进程尝试继续,但进程一次又一次地重复到相同的状态。
(在死锁计算中,没有可能成功的执行序列。但在活锁计算中,有成功的计算,但有一个或多个执行序列,其中没有进程进入其临界区。)
与死锁和死锁的区别livelock
当死锁发生时,不会发生任何执行。但在活锁中,会发生一些执行,但这些执行不足以进入临界区。
I just planned to share some knowledge.
Deadlocks
A set of threads/processes is deadlocked, if each thread/process in the set is waiting for an event that only another process in the set can cause.
The important thing here is another process is also in the same set. that means another process also blocked and no one can proceed.
Deadlocks occur when processes are granted exclusive access to resources.
These four conditions should be satisfied to have a deadlock.
If we found these conditions then we can say there may be occurred a situation like a deadlock.
LiveLock
Each thread/process is repeating the same state again and again but doesn't progress further. Something similar to a deadlock since the process can not enter the critical section. However in a deadlock, processes are wait without doing anything but in livelock, the processes are trying to proceed but processes are repeated to the same state again and again.
(In a deadlocked computation there is no possible execution sequence which succeeds. but In a livelocked computation, there are successful computations, but there are one or more execution sequences in which no process enters its critical section.)
Difference from deadlock and livelock
When deadlock happens, No execution will happen. but in livelock, some executions will happen but those executions are not enough to enter the critical section.