线程死锁

线程死锁四个必要条件

  1. 互斥条件:一个资源每次只能被一个线程使用。
  2. 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:线程已获得的资源,在末使用完之前,不能强行剥夺。
  4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

下面来看看死锁例子:

线程饥饿死锁:在一个线程池中,如果一个任务依赖于其他任务的执行,就可能产生死锁。对应一个单线程话的Executor,一个任务将另一个任务提交到相同的Executor中,并等待新提交的任务的结果,这总会引发死锁。第二个任务滞留在工作队列中,直到第一个任务完成,但是第一个任务不会完成,因为它在等待第二个任务的完成。同样在一个大的线程池中,如果所有线程执行的任务都阻塞在线程池中,等待着仍然处于同一个工作队列中的其他任务,那么会发生同样的问题。这就是线程饥饿死锁。
举个例子:

package com.koma.demo;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author koma
 * @version 2017年12月8日 上午10:39:59
 */
public class ThreadDeadlock {
    public static ExecutorService exec = Executors.newSingleThreadScheduledExecutor();
    // 如果是newCachedThreadPool线程池,就不会发生饥饿死锁
//  public static ExecutorService exec = Executors.newCachedThreadPool();

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        Future<String> futre = exec.submit(new RenderPageTask());
        String result = futre.get();
        System.out.println("执行结果为:" + result);
        exec.shutdown();
    }
}

class RenderPageTask implements Callable<String> {
    @Override
    public String call() throws Exception {
        Future<String> header, footer;

        header = ThreadDeadlock.exec.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("加载页眉");
                return "页眉";
            }
        });

        footer = ThreadDeadlock.exec.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("加载页脚");
                return "页脚";
            }
        });

        System.out.println("渲染页面主体");
        // 等待返回, exec线程池是单线程,如果是多线程的话,就不存在饥饿死锁了。
        return header.get() + footer.get();
    }

}

简单的顺序死锁

package com.koma.demo.deadlock;

/**
 * @author koma
 * @version 2017年12月9日 上午11:15:53
 * 简单的锁顺序死锁
 */
public class LeftRightDeadlock {
    private final Object left = new Object();
    private final Object right = new Object();

    public void leftRigth() {
        // 线程A获得left对象锁
        synchronized (left) {
            // 线程A准备获得right对象锁,此时线程B已经获得right对象锁
            synchronized (right) {
                System.out.println("leftRight");
            }
        }
    }

    public void rightLeft() {
        // 线程B获得right对象锁
        synchronized (right) {
            // 线程B准备获得left,但是线程A还没有释放left对象锁
            synchronized (left) {
                System.out.println("rightLeft");
            }
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值