java小易——锁

①按照其性质分类

公平锁/非公平锁:

公平锁是指多个线程按照申请锁的顺序来获取锁。非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。对于Synchronized而言,也是一种非公平锁

乐观锁/悲观锁

指看待并发同步的角度

悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。

乐观锁则认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,会采用尝试更新,不断重新的方式更新数据。乐观的认为,不加锁的并发操作是没有事情的,**无锁编程,**常常采用的是CAS算法,典型的例子就是原子类,通过CAS自旋实现原子操作的更新。

悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多的场景

独享锁/共享锁

独享锁是指该锁一次只能被一个线程所持有。共享锁是指该锁可被多个线程所持有

对于Java ReentrantLock而言,其是独享锁。但是对于Lock的另一个实现类ReentrantReadWriteLock,其读锁是共享锁,其写锁是独享锁

对于Synchronized而言,当然是独享锁。

互斥锁/读写锁

上面讲的独享锁/共享锁就是一种广义的说法,互斥锁/读写锁就是具体的实现。互斥锁在Java中的具体实现就是ReentrantLock读写锁在Java中的具体实现就是ReentrantReadWriteLock

可重入锁

可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。

Reentrant Lock重新进入锁。对于Synchronized而言,也是一个可重入锁。

可重入锁的一个好处是可一定程度避免死锁。

②按照设计方案来分类

自旋锁/自适应自旋锁

在Java中,自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。自旋次数的默认值是10次

偏向锁/轻量级锁/重量级锁

这三种锁是指锁的状态,并且是针对Synchronized。

这三种锁的状态是通过对象监视器在对象头中的字段来表明的

偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。

轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。

重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。

如果锁竞争时间短,可以使用自旋锁进一步优化轻量级锁、重量级锁的性能,减少线程切换。
如果锁竞争程度逐渐提高(缓慢),那么从偏向锁逐步膨胀到重量锁,能够提高系统的整体性能。

锁膨胀的过程:只有一个线程进入临界区(偏向锁),多个线程交替进入临界区(轻量级锁),多线程同时进入临界区(重量级锁)。

请解释偏向锁,轻量级锁,自选锁的区别

偏向锁的优点是加解锁不需要额外消耗,和执行非同步方法比仅存在纳秒级差距,缺点是如果存在锁竞争会带来额外锁撤销的消耗,适用只有一个线程访问同步代码块的场景。

轻量级锁的优点是竞争线程不阻塞,程序响应速度快,缺点是如果线程始终得不到锁会自旋消耗 CPU,适用追求响应时间、同步代码块执行快的场景。

自旋锁的优缺点:如果锁的竞争不激烈,且占用锁时间非常短的代码块来说性能能大幅度的提升,因为自旋的消耗会小于线程阻塞挂起操作的消耗!

但是如果锁的竞争激烈,或者持有锁的线程需要长时间占用锁执行同步块,这时线程自旋的消耗大于线程阻塞挂起操作的消耗,其它需要cup的线程又不能获取到cpu,就会造成cpu的浪费。

重量级锁的优点是线程竞争不使用自旋不消耗CPU,缺点是线程会阻塞,响应时间慢,适应追求吞吐量、同步代码块执行慢的场景。

锁升级的过程:

​ 在多线程情况下,当一个线程A去调用一个共享资源时,为了防止别的线程B在线程A执行的过程中去调用这个公共资源,会给这个公共资源加上偏向锁,其他线程会进入就绪队列(并不会挂起),当线程B去调用这个公共资源的时候,偏向锁会自动升级为轻量级锁,当线程B 再次去调用这个公共资源的时候,轻量级锁会再次自动升级为自旋锁,这时线程B不会 再主动获得资源,而是锁自旋,看自己的锁是否被释放掉,如果释放掉了它就会通知线程B来获得资源,当自旋锁自旋10次之后,会自动升级为重量级锁,此时线程B挂起。
锁升级过程适用于低并发,为了快速响应,当高并发时,其他线程会直接进入到挂起状态。

分段锁

分段锁其实是一种锁的设计,并不是具体的一种锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作

分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。


Synchronized和Lock

以下一个锁是原生语义上的实现

  • Synchronized,它就是一个:非公平,悲观,独享,互斥,可重入的重量级锁

以下两个锁都在JUC包下,是API层面上的实现

  • ReentrantLock,它是一个:默认非公平但可实现公平的,悲观,独享,互斥,可重入,重量级锁。
  • ReentrantReadWriteLocK,它是一个,默认非公平但可实现公平的,悲观,写独享,读共享,读写,可重入,重量级锁。

1、ReentrantLock获取锁定与三种方式:
a) lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁

b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;

c)tryLock(long timeout,TimeUnit unit),如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;

d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断

区别:
synchronizedLock
存在层次Java的关键字是一个接口
锁的释放1、以获取锁的线程执行完同步代码,释放锁。2、线程执行发生异常、jvm会让线程释放锁在finally中必须释放锁,不然容易造成线程死锁
锁的获取假设A线程获得锁,B线程等待,如果A线程阻塞,B线程会一直等待Lock可以让等待锁的线程响应中断
锁状态无法判断可以判断有没有成功获取锁
锁类型可重入 不可判断 非公平可重入 可中断 公平/非公平

2、synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中

3,在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;

synchronized的优势

synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中

缺点:synchronized无法中断一个正在等待获得锁的线程,也即多线程竞争一个锁时,其余未得到锁的线程只能不停的尝试获得锁,而不能中断。这种情况对于大量的竞争线程会造成性能的下降等后果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值