首页 > 其他 > 详细

JUC---13各种锁

时间:2020-06-08 16:26:14      阅读:36      评论:0      收藏:0      [点我收藏+]

一、公平锁与非公平锁

  公平锁:加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得

  非公平锁:加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待

  非公平锁性能比公平锁高5~10倍,因为公平锁需要在多核的情况下维护一个队列。Java中的ReentrantLock 默认的lock()方法采用的是非公平锁。通过调用有参构造设置是否为公平与非公平锁

   技术分享图片

 

 二、可重入锁(递归锁)

  1.广义上的可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁。ReentrantLock和synchronized都是可重入锁

  2.特点:获取到外面的锁,就能拿到里面的锁(自动获取;就像自己家一样,拿钥匙开门之后,进卧室不用开锁)

    3.代码:

public class MyDemo {
    public static void main(String[] args) {
        testLock();
    }

    public static void testSynchronized() {
        Phone phone = new Phone();
        new Thread(() -> {
            phone.sms();
        }, "A").start();
        new Thread(() -> {
            phone.sms();
        }, "B").start();
    }

    public static void testLock() {
        Phone2 phone = new Phone2();
        new Thread(() -> {
            phone.sms();
        }, "A").start();
        new Thread(() -> {
            phone.sms();
        }, "B").start();
    }
}

class Phone {
    public synchronized void sms() {
        System.out.println(Thread.currentThread().getName() + "sms");
        call(); // 这里也有锁
    }

    public synchronized void call() {
        System.out.println(Thread.currentThread().getName() + "call");
    }
}

class Phone2 {
    Lock lock = new ReentrantLock();

    public void sms() {
        lock.lock(); // 细节问题:lock.lock(); lock.unlock(); // lock 锁必须配对,否则就会死在里面
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "sms");
            call(); // 这里也有锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            lock.unlock();
        }
    }

    public void call() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "call");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

 

三、自旋锁

  1.是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。获取锁的线程一直处于活跃状态,但是并没有执行任何有效的任务,使用这种锁会造成busy-waiting。

  2.在CAS中,Unsafe类里面的方法getAndAddInt()里面就是实现的自旋锁

  代码:

public class MyDemo {

    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    // 加锁
    public void myLock() {
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + "==> mylock");
        // 自旋锁
        while (!atomicReference.compareAndSet(null, thread)) {

        }
    }

    // 解锁
    public void myUnLock() {
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + "==> myUnlock");
        atomicReference.compareAndSet(thread, null);
    }

    public static void main(String[] args) throws InterruptedException {
        MyDemo lock = new MyDemo();

        new Thread(() -> {
            lock.myLock();
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.myUnLock();
            }
        }, "T1").start();

        TimeUnit.SECONDS.sleep(1);

        new Thread(() -> {
            lock.myLock();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.myUnLock();
            }
        }, "T2").start();
    }
}

 

四、死锁

  1.死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去

  2.死锁产生的必要条件

    互斥条件、请求和保持条件、不剥夺条件、环路等待条件

  3.死锁产生的原因:

    竞争不可抢占性资源(或竞争可消耗资源)、进程推进顺序不当

  4.避免与解决死锁的算法:死锁预防(有序资源分配法、银行家算法)   解决死锁(死锁预防、死锁避免、死锁检测和解除)

  5.java中发生死锁的查看方式

    1.运行发生死锁的代码

    2.在程序运行时,使用  jps -l查看当前进程号

    3.使用jstack 进程号找到死锁问题

 

JUC---13各种锁

原文:https://www.cnblogs.com/jenne-blog/p/13058083.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!