ReentrantLock基本介绍


一、ReentrantLock是什么?

  jdk1.5新增了并发包,里面包含Lock接口,与synchronized关键字一样能实现同步功能,但相比synchronized,Lock更加灵活,可以手动获取、释放锁,而ReentrantLock就是Lock的一个实现类。

二、基本使用

1、可重入锁

  ReentrantLock从字面意思翻译就是可重入锁,那什么是可重入锁?简单来说就是某个线程获取改锁后,可以重复的进入改锁锁住的代码。ReentrantLock也是可重入锁,但是要注意的是,因为ReentrantLock需要自己手动加锁、解锁,所以加锁几次就必须解锁几次,不然其他线程就没法获取资源。

public class Main6 {


    public static void main(String[] args)  {

        ReentrantLock lock = new ReentrantLock();
        f1(lock);
    }

    public static void f1(ReentrantLock lock){
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "第1次");
            f2(lock);
        }finally {
            lock.unlock();
        }
    }

    public static void f2(ReentrantLock lock){
        try {
            lock.lock(); // 这里再次加锁
            System.out.println(Thread.currentThread().getName() + "第2次");
        }finally {
            lock.unlock();
        }
    }
}

输出:

main第1次
main第2次

2、非公平锁与公平锁

  非公平锁就是多个线程抢夺资源时,不分先来后到,只拼手速,算抢到算谁的,ReentrantLock默认情况下就是非公平锁。

public class Main1 {

    public static void main(String[] args) {
        Ticket ticket = new Ticket();

        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                ticket.sale();
            }
        },"A").start();

        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                ticket.sale();
            }
        },"B").start();

        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                ticket.sale();
            }
        },"C").start();
    }

}

class Ticket{
    private int count = 20;
    // 默认非公平锁
    private ReentrantLock lock = new ReentrantLock();

    public void sale(){
        try {
            lock.lock();
            if(count > 0){
                count--;
                System.out.println(Thread.currentThread().getName() + ":卖出1张,剩余" + count);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
}

可以看出这一轮中B压根都没抢到,输出:

A:卖出1张,剩余19
A:卖出1张,剩余18
A:卖出1张,剩余17
A:卖出1张,剩余16
C:卖出1张,剩余15
C:卖出1张,剩余14
C:卖出1张,剩余13
C:卖出1张,剩余12
C:卖出1张,剩余11
C:卖出1张,剩余10
C:卖出1张,剩余9
C:卖出1张,剩余8
C:卖出1张,剩余7
C:卖出1张,剩余6
C:卖出1张,剩余5
C:卖出1张,剩余4
C:卖出1张,剩余3
C:卖出1张,剩余2
C:卖出1张,剩余1
C:卖出1张,剩余0

  那公平锁就是多个线程抢夺资源时,会按照你请求获取锁的时间先来后到,能够尽可能的雨露均沾。ReentrantLock设置成公平锁只需要在构造方法传入true,表示当前是公平锁。所以更改上述代码:

class Ticket{
    private int count = 20;
    // 公平锁
    private ReentrantLock lock = new ReentrantLock(true);

    public void sale(){
        ...
    }

现在可以看到三个线程均获取到过资源。

A:卖出1张,剩余19
A:卖出1张,剩余18
A:卖出1张,剩余17
A:卖出1张,剩余16
A:卖出1张,剩余15
B:卖出1张,剩余14
C:卖出1张,剩余13
A:卖出1张,剩余12
B:卖出1张,剩余11
C:卖出1张,剩余10
A:卖出1张,剩余9
B:卖出1张,剩余8
C:卖出1张,剩余7
A:卖出1张,剩余6
B:卖出1张,剩余5
C:卖出1张,剩余4
A:卖出1张,剩余3
B:卖出1张,剩余2
C:卖出1张,剩余1
A:卖出1张,剩余0

三、小结

  ReentrantLock除了上面提到多的是可重入锁、公平锁、非公平锁外,它也是独占锁,独占锁就是任何时候都只有一个线程能得到锁,那ReentrantLock与synchronized的区别:

  • 性能
    目前优化后,synchronized与ReentrantLock性能其实已经没什么太大区别。
  • 灵活性
    这个一目了然,ReentrantLock肯定比synchronized更加灵活,自行加锁、解锁。并且synchronized只能是非公平锁,而ReentrantLock可以设定成非公平锁或公平锁。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值