java多线程学习笔记2-可重入锁与死锁

(本文为廖雪峰java学习笔记)
能被同一个线程反复获取的锁叫做可重入锁。

public class Counter {
    private int count = 0;

    public synchronized void add(int n) {
        if (n < 0) {
            dec(-n);//对同一个线程,能在获取到锁以后继续获取同一个锁。
        } else {
            count += n;
        }
    }

    public synchronized void dec(int n) {
        count += n;
    }
}

在n<0分支里dec(-n)方法可以执行下去,因为JVM允许同一个线程重复获取同一个锁,每获取一次锁,记录+1,每退出synchronized块,记录-1,减到0的时候,才会真正释放锁。

什么是死锁?多个线程互相等待对方释放持有的资源就会造成死锁。比如下面代码,如果两个线程分别执行add和dec方法则会造成死锁。

public void add(int m) {
    synchronized(lockA) { // 获得lockA的锁
        this.value += m;
        synchronized(lockB) { // 获得lockB的锁
            this.another += m;
        } // 释放lockB的锁
    } // 释放lockA的锁
}

public void dec(int m) {
    synchronized(lockB) { // 获得lockB的锁
        this.another -= m;
        synchronized(lockA) { // 获得lockA的锁
            this.value -= m;
        } // 释放lockA的锁
    } // 释放lockB的锁
}

避免死锁的方法是,线程获取锁的顺序要一致。上面的代码按如下改则可以避免死锁(方法add和dec获取锁的顺序都一样):

public void add(int m) {
    synchronized(lockA) { // 获得lockA的锁
        this.value += m;
        synchronized(lockB) { // 获得lockB的锁
            this.another += m;
        } // 释放lockB的锁
    } // 释放lockA的锁
}

public void dec(int m) {
    synchronized(lockA) { // 获得lockA的锁
        this.another -= m;
        synchronized(lockB) { // 获得lockB的锁
            this.value -= m;
        } // 释放lockB的锁
    } // 释放lockA的锁
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值