美文网首页
线程锁Lock

线程锁Lock

作者: 林亚希 | 来源:发表于2019-03-15 10:54 被阅读0次

    有了synchronized为什么还要Lock?

    1.首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
    2.synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
    3.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
    4.用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
    5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)
    6.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。

    Lock的常用API

    • Lock()
    • lockInterruptibly:可中断
    • tryLock尝试非阻塞地获取锁
    • unlock()

    首先lock()方法是平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。

    由于在前面讲到如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。通常使用Lock来进行同步的话,是以下面这种形式去使用的:

    Lock lock = ...;
    lock.lock();
    try{
        //处理任务
    }catch(Exception ex){
         
    }finally{
        lock.unlock();   //释放锁
    }
    

    lockInterruptibly()方法比较特殊,当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。也就使说,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。

    由于lockInterruptibly()的声明中抛出了异常,所以lock.lockInterruptibly()必须放在try块中或者在调用lockInterruptibly()的方法外声明抛出InterruptedException。

    因此lockInterruptibly()一般的使用形式如下:

    public void method() throws InterruptedException {
        lock.lockInterruptibly();
        try {  
         //.....
        }
        finally {
            lock.unlock();
        }  
    }
    

    公平和非公平锁

    公平锁,先对锁发出获取请求的一定先被满足。公平锁的效率比非公平锁效率要低。

    读写锁ReentrantReadWriteLock

    允许多个读线程同时进行,但是只允许一个写线程(不允许其他读线程和写线程),支持读多写少场景,性能会有提升。

    Condition接口有何用处?

    Object wait,notify/all Condition接口和Lock配合来实现等待通知机制

    相关文章

      网友评论

          本文标题:线程锁Lock

          本文链接:https://www.haomeiwen.com/subject/hpbqmqtx.html