mah*_*mah 372
取自http://en.wikipedia.org/wiki/Deadlock:
在并发计算中,死锁是一组操作中的每个成员正在等待某个其他成员释放锁的状态
阿活锁类似于死锁,不同之处在于所涉及的活锁的过程的状态不断地相对于彼此改变,没有取得进展.活锁是资源匮乏的特例; 一般定义仅表明特定过程没有进展.
当两个人在狭窄的走廊中相遇时,会发生一个真实的活锁示例,每个人都试图通过移动到另一个通过来礼貌,但他们最终会左右摇摆而没有任何进展,因为他们都反复移动以同样的方式同时进行.
Livelock是一种风险,有些算法可以检测并从死锁中恢复.如果多个进程采取行动,则可以重复触发死锁检测算法.通过确保只有一个进程(随机选择或按优先级)采取行动,可以避免这种情况.
Bur*_*man 76
线程通常用于响应另一个线程的操作.如果另一个线程的操作也是对另一个线程的操作的响应,则可能导致活锁.
与死锁一样,活锁线程无法取得进一步进展.但是,线程没有被阻塞 - 他们只是太忙于相互回应以恢复工作.这相当于两个试图在走廊里互相通过的人:Alphonse向左移动让Gaston通过,而Gaston向右移动让Alphonse通过.看到他们仍在相互阻挡,Alphonse向右移动,而Gaston向左移动.他们还在互相阻挡,等等......
活锁和死锁之间的主要区别在于线程不会被阻塞,而是会尝试连续响应彼此.
在此图像中,两个圆(线程或进程)将尝试通过向左和向右移动为另一个提供空间.但他们无法继续前进.

Dan*_*ite 59
这里的所有内容和示例都来自
操作系统:与设计原理
威廉·斯托林斯
8º版
死锁:两个或多个进程无法继续进行的情况,因为每个进程都在等待其他进程执行某些操作.
例如,考虑两个进程P1和P2,以及两个资源R1和R2.假设每个进程都需要访问这两个资源来执行其部分功能.然后可能出现以下情况:OS将R1分配给P2,R2分配给P1.每个进程都在等待两个资源中的一个.在获得其他资源并执行需要两种资源的功能之前,它们都不会释放它已拥有的资源.这两个进程陷入僵局
Livelock:一种情况,其中两个或多个进程连续更改其状态以响应其他进程的更改而不执行任何有用的工作:
饥饿:调度程序无限期忽略可运行进程的情况; 虽然它能够继续下去,但它永远不会被选中.
假设三个进程(P1,P2,P3)都需要定期访问资源R.考虑P1拥有资源的情况,P2和P3都被延迟,等待该资源.当P1退出其临界区时,应允许P2或P3访问R.假设操作系统授予对P3的访问权限,并且在P3完成其关键部分之前,P1再次需要访问权限.如果操作系统在P3完成后授予对P1的访问权限,并随后交替授予对P1和P3的访问权限,则P2可能无限期地被拒绝访问资源,即使没有死锁情况.
附录A - 同意的主题
死锁示例
如果两个进程在执行while语句之前将其标志设置为true,则每个进程都会认为另一个已进入其临界区,从而导致死锁.
/* PROCESS 0 */
flag[0] = true;
while (flag[1])
/* do nothing */;
/* critical section*/;
flag[0] = false;
/* PROCESS 1 */
flag[1] = true;
while (flag[0])
/* do nothing */;
/* critical section*/;
flag[1] = false;
Run Code Online (Sandbox Code Playgroud)
活锁示例
/* PROCESS 0 */
flag[0] = true;
while (flag[1]){
flag[0] = false;
/*delay */;
flag[0] = true;
}
/*critical section*/;
flag[0] = false;
/* PROCESS 1 */
flag[1] = true;
while (flag[0]) {
flag[1] = false;
/*delay */;
flag[1] = true;
}
/* critical section*/;
flag[1] = false;
Run Code Online (Sandbox Code Playgroud)
[...]考虑以下事件序列:
这个序列可以无限延长,任何一个过程都不能进入其关键部分.严格地说,这不是死锁,因为两个过程的相对速度的任何改变都将打破这个循环并允许一个人进入临界区.这种情况称为活锁.回想一下,当一组进程希望进入其关键部分但没有进程能够成功时,会发生死锁.对于活锁,有可能的执行序列成功,但也可以描述一个或多个执行序列,其中没有进程进入其关键部分.
Dee*_*ane 13
DEADLOCK 死锁是一种条件,在这种情况下,任务无限期地等待永远不能满足的条件 - 任务声明对共享资源的独占控制 - 任务在等待释放其他资源时保留资源 - 不能强制任务重新启动资源 - 循环等待条件存在
LIVELOCK 当两个或多个任务依赖并使用某个资源导致循环依赖条件,其中这些任务继续永久运行时,可能会出现Livelock条件,从而阻止所有较低优先级的任务运行(这些较低优先级的任务会遇到称为饥饿的情况)
也许这两个示例向您说明了死锁和活锁之间的区别:
Java-死锁示例:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DeadlockSample {
private static final Lock lock1 = new ReentrantLock(true);
private static final Lock lock2 = new ReentrantLock(true);
public static void main(String[] args) {
Thread threadA = new Thread(DeadlockSample::doA,"Thread A");
Thread threadB = new Thread(DeadlockSample::doB,"Thread B");
threadA.start();
threadB.start();
}
public static void doA() {
System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
lock1.lock();
System.out.println(Thread.currentThread().getName() + " : holds lock 1");
try {
System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
lock2.lock();
System.out.println(Thread.currentThread().getName() + " : holds lock 2");
try {
System.out.println(Thread.currentThread().getName() + " : critical section of doA()");
} finally {
lock2.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
}
} finally {
lock1.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
}
}
public static void doB() {
System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
lock2.lock();
System.out.println(Thread.currentThread().getName() + " : holds lock 2");
try {
System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
lock1.lock();
System.out.println(Thread.currentThread().getName() + " : holds lock 1");
try {
System.out.println(Thread.currentThread().getName() + " : critical section of doB()");
} finally {
lock1.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
}
} finally {
lock2.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
}
}
}
Run Code Online (Sandbox Code Playgroud)
样本输出:
Thread A : waits for lock 1
Thread B : waits for lock 2
Thread A : holds lock 1
Thread B : holds lock 2
Thread B : waits for lock 1
Thread A : waits for lock 2
Run Code Online (Sandbox Code Playgroud)
活锁的Java示例:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LivelockSample {
private static final Lock lock1 = new ReentrantLock(true);
private static final Lock lock2 = new ReentrantLock(true);
public static void main(String[] args) {
Thread threadA = new Thread(LivelockSample::doA, "Thread A");
Thread threadB = new Thread(LivelockSample::doB, "Thread B");
threadA.start();
threadB.start();
}
public static void doA() {
try {
while (!lock1.tryLock()) {
System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + " : holds lock 1");
try {
while (!lock2.tryLock()) {
System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + " : holds lock 2");
try {
System.out.println(Thread.currentThread().getName() + " : critical section of doA()");
} finally {
lock2.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
}
} finally {
lock1.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
}
} catch (InterruptedException e) {
// can be ignored here for this sample
}
}
public static void doB() {
try {
while (!lock2.tryLock()) {
System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + " : holds lock 2");
try {
while (!lock1.tryLock()) {
System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + " : holds lock 1");
try {
System.out.println(Thread.currentThread().getName() + " : critical section of doB()");
} finally {
lock1.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
}
} finally {
lock2.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
}
} catch (InterruptedException e) {
// can be ignored here for this sample
}
}
}
Run Code Online (Sandbox Code Playgroud)
样本输出:
Thread B : holds lock 2
Thread A : holds lock 1
Thread A : waits for lock 2
Thread B : waits for lock 1
Thread B : waits for lock 1
Thread A : waits for lock 2
Thread A : waits for lock 2
Thread B : waits for lock 1
Thread B : waits for lock 1
Thread A : waits for lock 2
Thread A : waits for lock 2
Thread B : waits for lock 1
...
Run Code Online (Sandbox Code Playgroud)
这两个示例都强制线程以不同的顺序获取锁。当死锁等待另一个锁时,活动锁实际上并没有真正等待-它拼命尝试获取该锁而没有机会获得它。每次尝试都会消耗CPU周期。