java死锁的三个例子

6 篇文章 0 订阅
1 篇文章 0 订阅

例子1: 锁顺序引发的死锁

private final Object left = new Object();
    private final Object right = new Object();
    
    public void leftRigth(){
        synchronized (left){
            synchronized (right){
                System.out.println("leftRigth");
            }
        }
    }

    public void rightLeft(){
        synchronized (right){
            synchronized (left){
                System.out.println("rightLeft");
            }
        }
    }

 启用两个线程,一个调用leftRight()方法,一个调用rightLeft()方法,并且这两个线程交错的执行,它们就会发生死锁。

例子2:单线程死锁

public static void main(String[] args){

        RenderPageTask renderPageTask = new RenderPageTask();
        renderPageTask.executor.submit(renderPageTask);

    }

:

public class RenderPageTask implements Callable<String> {
    ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("wxAuth-pool-%d").build();
    public ExecutorService executor = new ThreadPoolExecutor(1, 1,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(),threadFactory);

    @Override
    public String call() throws ExecutionException, InterruptedException {
        System.out.println("进入了。。");
        Future<String> header;
        header = (Future<String>) executor.submit(()->{System.out.println("22");});
        return header.get();
    }
}

使用单线程的线程池,提交一个任务A到线程池,然后再执行A这个任务的过程中在给线程池提交一个任务B。由于是单线程的线程池,所以任务B的执行需要等待任务A执行完才能获得线程。但是A的执行完毕又依赖B,所以就形成了死锁。

 

例子3:动态的锁顺序死锁

在例子1中,锁的顺序是固定的。在实际的操作过程中可能锁时动态的,比如支付场景中,x向y转钱,这个过程需要时原子性的,所以需要对金额的计算进行加锁。这个过程要对x与y的金额都要上锁,所以有两个锁。但是,可能有一个线程从x向y转账,一个线程从y向x转账,这样就形成了动态的死锁。要避免这样动态锁的顺序造成的死锁问题,可以指定锁的顺序,使用Object.hashCode返回的值去决定先加那个锁,让每次锁的顺序都是一样的。比如前面的例子,不管是x向y转钱还是y向x转钱他们上锁的顺序都是一样的。可能都是先给x加锁。

但是,也有可能两个对象拥有相同的散列值,这时必须通过某种任意的方法来决定锁的顺序,但是这可能又引入死锁。为了避免这种情况,可以使用“加时赛”锁。

 

参考资料:

《java并发编程实战》

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值