死锁,饥饿,活锁

本文深入探讨了多线程编程中的死锁和线程饥饿现象,解析了死锁的四个必要条件及线程饥饿的成因,通过具体实例阐述两者之间的区别与联系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

鹬蚌相争:死锁

死锁是一种常见的活性故障,如果两个或者更多的线程因相互等待对方而被永远暂停(生命周期为BLOCKED或者WAITING),那么就称这鞋线程产生了死锁。
多线程产生死锁的四个必要条件:
1、互斥条件:任意时刻一个资源只能给一个进程使用,其他进程若申请一个资源,而该资源被另一进程占有时,则申请
者等待直到资源被占有者释放。
2、不可剥夺条件:进程所获得的资源在未使用完毕之前,不被其他进程强行剥夺,而只能由获得该资源的进程资源释放。
3、请求和保持条件:进程每次申请它所需要的一部分资源,在申请新的资源的同时,继续占用已分配到的资源。
4、循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

巧妇难为无米之炊: 线程饥饿

线程饥饿( Thread Starvation )是指线程一直无法获取其所需的资源而导致其任务无法进展的一种活性故障。
线程饥饿的一个典型例子是在高争用的环境下使用非公平模式(Non-fir mnde )的读写锁(ReentrantReadWriteLock)。 例如,在Web应用程序中使用ReentrantReadWriteLocok读写锁来保护配置数据, 业务线程可能不断地申请读写锁的读锁来读取配置数据,由于默认情改下ReCcaraeWreteLroe的锁调度采用非公平调度模式,因此如果这些业务线程对锁合争用程星度比较高,那么系统管理模块试图更新配置数据的时候就可能遇到这样的情形:相应的读锁锁总是被业务线程抢先占有(非公平锁调度可能导致的结果)导致系统管理模块线程始终无法获得相应的写锁,从而使其一直无法更新配置数据。 因此,尽管非公平锁支持更高的吞吐率,但是它也可能导致某些线程总是无法获取其所需的资源(锁),导致线程饥饿。
把锁看作一种资源,那么我们不难发现死锁也是一种线程饥饿。死锁的结果是故障线程都无法获得其所需的全部锁中的一个锁,从而使其任务一直无法进展, 这相当于线法获得其所需的全部资源(锁)而使得其任务一 直无法进展,即产生了线程饥饿。由程饥饿的产生条件是一个(或者多个)线程始终无法获取其所需的资源,显然这个条满足并不意味着死锁产生的必要条件(这还仅是必要条件,而不是充分条件)的满足此线程饥饿并不会导致死锁。
线程饥饿涉及的线程,其生命周期状态不一定就是 WATING或者BLOCKED其伏态也可能是RUNNING (这说明涉及的线程直在电请其所需的资源), 这时演变成活锁。

屡战屡败, 屡败屡战:活锁

活锁( Livelock )是指线程一直处于运行状态, 但是其任务却一直无法进展的性战体,也就是说,产生活锁的线程一直在做无用功,这就好比小猫咬自己的尾巴,虽然一直在咬,但是却直咬不到自己的尾巴。

Java中的死锁多线程并发编程中的常见问题,这些问题可能会导致线程无法向前执行或陷入死循环。下面分别介绍Java死锁的概念和案例。 1. 死锁 死锁是指两个或多个线程相互等待对方释放,从而导致所有线程都无法向前执行的状态。简单来说,当两个或多个线程都占有某些资源并且又想要获取对方占有的资源时,就会发生死锁。 下面是一个Java中的死锁例子: ```java public class DeadlockExample { private Object lock1 = new Object(); private Object lock2 = new Object(); public void method1() { synchronized (lock1) { System.out.println("Method 1: Holding lock 1..."); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2) { System.out.println("Method 1: Holding lock 1 and lock 2..."); } } } public void method2() { synchronized (lock2) { System.out.println("Method 2: Holding lock 2..."); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1) { System.out.println("Method 2: Holding lock 1 and lock 2..."); } } } public static void main(String[] args) { DeadlockExample example = new DeadlockExample(); Thread t1 = new Thread(() -> example.method1()); Thread t2 = new Thread(() -> example.method2()); t1.start(); t2.start(); } } ``` 在这个例子中,两个线程t1和t2分别调用了method1和method2方法,这两个方法都需要获取lock1和lock2两个才能继续执行。由于t1占用了lock1并等待lock2,而t2占用了lock2并等待lock1,因此两个线程都无法释放自己占用的,从而陷入死锁状态。 2. 是指线程们都在运行并尝试执行任务,但是由于某些条件始终无法满足,导致线程们一直在重试,但是最终无法完成任务。这种情况下,线程们看起来像是在不断地动,但是实际上却没有任何进展。 下面是一个Java中的例子: ```java public class LiveLockExample { private boolean isPolite; public LiveLockExample(boolean isPolite) { this.isPolite = isPolite; } public void bow(LiveLockExample partner) { while (true) { if (isPolite) { System.out.println("I'm polite, I'll bow first"); partner.bowBack(this); isPolite = false; break;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值