Java中锁的了解

1.公平锁和非公平锁

定义:
        公平锁是指多个线程按照申请锁的顺序来获取锁,类似排队打饭,先来后到。
        非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。在高并发的情况下,有可能会造成优先级反转或者饥饿现象。

 哪些属于:

        并发包中ReentrantLock的创建可以指定构造函数的boolean类型来得到公平锁或非公平锁,默认是非公平锁。

公平锁和非公平锁的区别:
    1.公平锁,就是很公平,在并发环境中,每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个,就占有锁,否则就会加入到等待队列中,以后会按照FIFO的规则从队列中取到自己
    2.非公平锁比较粗鲁,上来就直接尝试占有锁,如果尝试失败,就再采用类似公平锁那种方式。
    3.非公平锁的优点在于吞吐量比公平锁大。
    4.对于Synchronized而言,也是一种非公平锁

2.可重入锁(递归锁)


定义:

        指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁,这样的锁就叫做可重入锁。

哪些属于:

        synchronized关键字(隐式锁)、ReentrantLock类(显式锁)

        synchronized默认是可重入锁,简单的来说就是:在一个synchronized修饰的方法或代码块的内部调用本类的其他synchronized修饰的方法或代码块时,是永远可以得到锁的。

原理:
        每个锁对象拥有一个锁计数器和一个指向持有该锁的线程的指针。

        当执行monitorenter时,如果目标锁对象的计数器为零,那么说明它没有被其他线程所持有,Java虚拟机会将该锁对象的持有线程设置为当前线程,并且将其计数器加1。

        在目标锁对象的计数器不为零的情况下,如果锁对象的持有线程是当前线程,那么Java 虚拟机可以将其计数器加1,否则需要等待,直至持有线程释放该锁。

        当执行monitorexit时,Java虚拟机则需将锁对象的计数器减1。计数器为零代表锁己被释放。

        同步代码块的可重入锁演示,代码:

private static void reEntryM1() {
        Object object=new Object();
        new Thread(()->{
            synchronized(object){
                System.out.println(Thread.currentThread().getName()+"----外层调用");
                synchronized(object){
                    System.out.println(Thread.currentThread().getName()+"----中层调用");
                    synchronized(object){
                        System.out.println(Thread.currentThread().getName()+"----内层调用");
                    }
                }
            }
        },"t1").start();
    }

        结果:

        同步方法的可重入锁演示,代码: 

    private static void reEntryM2() {
        Test test = new Test();
        new Thread(()->{
            test.m1();
        },"t1").start();
    }

    public synchronized void m1(){
        System.out.println(Thread.currentThread().getName()+"---- m1 come in");
        m2();
        System.out.println(Thread.currentThread().getName()+"----m1 end");
    }
    public synchronized void m2(){
        System.out.println(Thread.currentThread().getName()+"----m2 come in");
        m3();
        System.out.println(Thread.currentThread().getName()+"----m2 end");
    }
    public synchronized void m3(){
        System.out.println(Thread.currentThread().getName()+"----m3 come in");
        System.out.println(Thread.currentThread().getName()+"----m3 end");
    }

        结果:

        ReentrantLock类的可重入锁演示,代码:

private static void reEntryM3() {
        ReentrantLock reentrantLock = new ReentrantLock();
        new Thread(()->{
            try {
                reentrantLock.lock();
                System.out.println(Thread.currentThread().getName()+"----外层调用");
                try {
                    reentrantLock.lock();
                    System.out.println(Thread.currentThread().getName()+"----中层调用");
                    try {
                        reentrantLock.lock();
                        System.out.println(Thread.currentThread().getName()+"----内层调用");
                    }finally {
                        reentrantLock.unlock();
                    }
                }finally {
                    reentrantLock.unlock();
                }
            }finally {
                reentrantLock.unlock();//加锁几次就要解锁几次,否则其他线程无法获取到该锁的资源
            }
        },"t1").start();
    }

        结果:

3.死锁

 
        多个线程在已经抢占到各自锁资源后,继续抢占对方的资源,无法抢到对方的资源就相互等待。

4.Java中底层锁的执行过程 :

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值