线程锁Lock

线程锁Lock

使用相较于synchronized更加灵活,在jdk5时性能比synchronized要好

在jdk7后,synchronized也升级了,单用性能上差不多(快慢),功能上lock更多

LOCK是接口

void lock():获取锁,如锁被占用则等待 相当于排队

boolean trylock():获取锁,获取成功返回true 相当于排号

void unlock():释放锁

实现类:

​ 一、重入锁:ReentrantLock,与synchronized一样具有互斥锁功能

​ Lock lock=new ReentrantLock() 可带参数,也可不带,(带参数即忽略线程优先级)

​ 1.释放锁需要确保即使发生异常也要释放,即需要放在finally里

​ 2.何为重入锁:当在一定的情形下,比如递归调用自身,也可以拿到锁,但是拿到锁的数量与释放锁的数量需要相同。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ik12huhP-1613900073951)(C:\Users\Think\AppData\Roaming\Typora\typora-user-images\image-20210117152350301.png)]

​ 二、读写锁:ReentrantReadWriteLock(支持递归调用)

​ 1.一种支持一写多读的同步锁,读写分离,可分别分配读和写锁

​ 2.支持多次分配读锁,使多个操作可以并发执行。

​ ReadLock() 读 WriteLock() 写

​ ReentrantReadWriteLock rwl=new ReentrantReadWriteLock()

​ ReadLock read=rwl.readLock()

​ WriteLock write=rwl.writeLock()

​ ReadLock 和WriteLock 是ReentrantReadWriteLock 的内部实现类

​ 读与写是分开的,有两把

​ 读:读操作不会改变数据,所以不需要互斥操作

​ 写:会改变数据,需要互斥操作

​ 当读比写多时,该锁效率比较高。

​ 互斥规则:

​ 写于写:互斥,阻塞

​ 读与写:互斥,读阻塞写,写阻塞读

​ 读与读:不互斥,不阻塞:读操作高于写操作

线程安全的集合

除了vector(Collection)和hashtable(map),其他集合都是线程不安全的

Vector

Vector和ArrayList类似,是长度可变的数组,与ArrayList不同的是,Vector是线程安全的,它给几乎所有的public方法都加上了synchronized关键字。由于加锁导致性能降低,在不需要并发访问同一对象时,这种强制性的同步机制就显得多余,所以现在Vector已被弃用。

HashTable

HashTable和HashMap类似,不同点是HashTable是线程安全的,它给几乎所有public方法都加上了synchronized关键字,还有一个不同点是HashTable的K,V都不能是null,但HashMap可以,它现在也因为性能原因被弃用了。

Collection接口下的:

虽然这些都不是线程安全的集合,但是可以使用工具类Collections来实现线程安全。

Collections提供了多个可以获得线程安全集合的方法。

​ List synArrayList = Collections.synchronizedList(new ArrayList());

​ Set synHashSet = Collections.synchronizedSet(new HashSet());

​ Map<K,V> synHashMap = Collections.synchronizedMap(new HashMap<K,V>());

底层实现:

​ 举例:ArrayList list=new ArrayList();

​ List safeList=Collections.synchronizedList(list);

​ safelist.add(“A”);

​ 当使用Collections.synchronizedList(list)变为安全时,由原先的ArrayList对象变为了安全的Collection&synchronizedCollection对象,此时它调用的add方法还是原先的ArrayList方法,但是在此方法之前加了一个锁(属性)对象(Final object matex),当多个线程访问这个集合时,相当于都需要拿到这个锁对象才能访问,那么此时就可以实现线程安全。

接口统一,维护性高,但性能没有提高,均已synchronized实现。(了解)

思想:代理(在外围进行包装)------>代理模式

CopeOnWriteArrayList

​ 相较于Collections工具类来实现安全集合,它单独做了包装。

​ 当遍历操作(读)多于写可变操作(写)是,该集合性能较好。

​ 线程安全的ArrayList,加强版的读写分离,优于读写锁:

​ why?

​ 在其底层使用了一个互斥锁(ReentrantLock),只在可变操作上加锁,而在读操作上不加锁,此时就只有写与写有互斥,因为其底层使用的是cope操作即开辟新空间进行添加数据,然后重新更新原数组的地址,那么此时就不会对正在读以及正在写造成影响。

CopeOnWriteArraySet

​ 线程安全的set,底层是CopeOnWriteArrayList实现

​ 唯一不同,使用addIfAbsent(),添加元素,遍历数组。

​ 区别:如何解决去重问题

​ 调用CopeOnWriteArrayList类里面的方法,多了利用for循环判断是否有重复数据,其他的操作是一样的。

ConcurrentHashMap

  • 初始容量认为16段(segment),使用分段锁设计。
  • 不对整个map加锁,而是为每个段加锁
  • 当多个对象存入同一个段时,才需要互斥
  • 最理想状态为16个对象分别存入16个段中,并行数量16
  • 使用方式与HashMap无异
Map<String, String> map = new ConcurrentHashMap<>();

Queue(接口)

队列,线程不安全

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nhDamcmY-1613900073963)(C:\Users\Think\AppData\Roaming\Typora\typora-user-images\image-20210118093752927.png)]

ConcurrentLinkedQueue

线程安全的Queue,可高效读写的队列,高并发下性能最好的队列

无锁,CAS比较交换算法,修改的方法包含三个参数(V,E,N)

V:要跟新的变量 E:预期值 N新值

只有当V==E时,V=N,否则表示已被更新,则取消当前操作

BlockingQueue(接口)

线程安全下进行通信

Queue的子接口,阻塞的队列,增加了两个线程状态为无限期等待的方法

可用于解决生产者、消费者问题。(线程通信问题)

实现类:

ArrayBlockingQueue

LinkedBlockingQueue

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值