我是靠谱客的博主 义气哑铃,最近开发中收集的这篇文章主要介绍Java的Lock锁和synchronized关键字的区别及其使用Java的Lock锁和synchronized关键字的区别及其使用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Java的Lock锁和synchronized关键字的区别及其使用

    一、synchronized关键字和Lock的区别以及优缺点

    我们可以回顾一下synchronized的使用,synchronized释放锁的时机有以下几种:
  1. 当执行完代码块中的代码,释放锁;
  2. 当代码抛出异常,释放锁;
  3. 当调用锁的wait方法,释放锁;

    以上三种情况便可以完全的帮我们解决线程同步的问题,为什么还要引入Lock呢?同样,synchronized关键字也有三种局限性:

  1. synchronized关键字无法响应中断,如果线程未获得锁,便会一直地尝试去获得锁,不会响应中断,lock锁的lockInterruptibly()方法能让线程响应中断,同时tryLock可以加入时间参数,若一定时间内未获得锁便返回,很灵活;
  2. synchronized关键字无法读写分离,在多个读线程访问临界资源时,是不需要同步的,但是synchronized关键字通通都给同步了,会导致效率很慢,Lock提供读写锁,实现读写分离;
  3. synchronized关键字无法知道线程是否获得锁;

    以上为synchronized的局限性,但是Lock也有他的缺点,Lock需要显式的释放锁,否则会造成死锁。

    接下来我们之上而下地看看Lock的类和接口吧...

    二、Lock接口

    Lock接口是最顶层的接口,提供的方法主要有这么几个:

    1、lock()

    lock()方法会尝试的获取锁,如果锁已经被其他线程给获取了,就会阻塞等待,需要注意的是,lock()需要显式地释放锁,如果发生异常也不会释放锁,所以很容易发生死锁,通常需要在finally中释放锁,保证锁一定被释放。

    2、tryLock()

    tryLock()会非阻塞地去获取锁,若获得锁则返回true,否则返回false,可以加入时间长度和时间单位参数,给线程一段等待的时间。

    3、lockInterruptibly()

    比较独特的一个用法,该方法获取锁时,若未获取到锁,等待阶段可以响应中断。在线程A和线程B竞争锁的时候,若线程B竞争失败,可以调用线程B的interrupt()方法打断线程B的阻塞状态。
    注意,interrupt()方法只能打断阻塞状态的线程,而不能打断已经获得锁的正在运行的线程。

    三、ReentrantLock类

    是唯一实现了Lock接口的类,重入锁(即,当一个线程已经获得了锁以后,当再次访问临界资源时,可以直接获得锁,synchronized关键字便是重入锁)。

    四、ReentrantReadWriteLock类

    ReentrantReadWriteLock类实现了ReadWriteLock接口,不过该接口只有两个方法,一个是获得读锁,一个是获得写锁。
    关于读写的冲突问题,掌握此三句:读读不冲突,读写冲突,写写冲突。

    五、Condition类

    Condition类提供wait()和notify()方法的替代,由锁实现,await()方法替代wait()方法,signal()和signalAll()方法替代notify()和notifyAll()方法,不同的是,一个Lock可以有多个Condition,而一个synchronized关键字只能有一个阻塞队列。

    如,在生产者消费者模型中,可以有两个Condition,一个用于提示仓库已满,一个用于提示仓库已空。

    以上便是Lock的全部内容,接下来介绍几种锁的概念:

    六、锁的概念

    1、重入锁

    上文已经提及,不赘述。

    2、可中断锁

    顾名思义,是可以响应中断的锁,synchronized关键字是非可中断锁,Lock是可中断锁。

    3、公平锁

    公平锁的含义就是,当多个线程等待同一个锁的时候,等待时间最久的线程获得即将释放的锁,即为公平,synchronized关键字是非公平的,Lock默认情况也是非公平的,但是可以在构造的时候,手动设置成公平锁。

    4、读写锁

    将读和写分为两个锁,使多个读线程不会相互等待。

    5、乐观锁和悲观锁

    两者都是顾名思义:乐观锁,就是一种很乐观的想法,认为自己在操作数据的时候,不会有其他任何的更新操作,所以在取数据的时候不加锁,只在提交更新的时候判断是否有人动过该数据,如使用版本号等机制。

    悲观锁,很悲观地认为在自己操作数据的时候,一定会有人操作数据,所以在取数据阶段就加锁,直到更新结束释放锁。数据库中的行锁,表锁,读锁,写锁都是悲观锁的实现。

    如此一分析,显然在读多写少的环境下,乐观锁会比较奏效,因为当并发量很大,乐观锁,便会不停地retry,降低效率。   

最后

以上就是义气哑铃为你收集整理的Java的Lock锁和synchronized关键字的区别及其使用Java的Lock锁和synchronized关键字的区别及其使用的全部内容,希望文章能够帮你解决Java的Lock锁和synchronized关键字的区别及其使用Java的Lock锁和synchronized关键字的区别及其使用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部