多线程进阶

本文深入探讨了多线程中的锁策略,包括悲观锁与乐观锁、读写锁与互斥锁、重量级锁与轻量级锁、挂起等待锁与自旋锁、公平锁与非公平锁以及可重入锁。此外,文章还讲解了CAS操作在解决线程安全问题上的应用,以及synchronized的优化机制,如锁膨胀和锁消除。最后,介绍了Java并发工具类,如Callable、ReentrantLock、Semaphore和CountDownLatch,以及线程安全的集合类在多线程环境下的使用。
摘要由CSDN通过智能技术生成

一、常见的锁策略

1、悲观锁&&乐观锁

悲观锁:预期锁冲突的概率很高,做的工作更多,付出的成本更多,更低效

乐观锁:预期锁冲突的概率很低,做的工作更少,付出的成本更低,更高效

2、读写锁&&普通的互斥锁

普通的互斥锁只有两个操作:加锁和解锁

读写锁有三个操作:加读(如果代码中只是进行读操作,就加读锁)、加写锁(如果代码中进行了修改操作,就加写锁)、解锁

针对读锁和读锁之间是不存在互斥关系的(因为多线程同时读同一个变量不会有线程安全问题),读锁和写锁之间,写锁和写锁之间才需要互斥

3、重量级锁&&轻量级锁

重量级锁:就是做了更多的事,开销比较大,通常情况下悲观锁一般都是重量级锁

轻量级锁:就是做了更少的事,开销比较小,通常情况下乐观锁一般都是轻量级锁

在使用锁的过程中,如果锁是基于内核的一些功能来实现的(比如调用了操作系统提供的mutex接口)此时一般认为这是重量级锁(操作系统会在内核中做很多事情,比如让线程阻塞等待)

如果锁是纯用户态来实现的,此时一般认为这是轻量级锁(用户态的代码更可控,也更高效)

4、挂起等待锁&&自旋锁

挂起等待锁:往往是通过内核的一些机制来实现的,往往较重 【重量级锁的一种典型实现】

自旋锁:往往就是通过用户态代码来实现的,往往较轻 【轻量级锁的一种典型实现】

5、公平锁&&非公平锁

公平锁:多个线程在等待一把锁的时候,谁是先来的,谁就能先获取到这个锁(遵循先来后到

非公平锁:多个线程在等待一把锁的时候,不遵守先来后到(每个线程获取到锁的概率都是均等的

6、可重入锁&&不可重入锁

一个线程针对一把锁,咔咔连续加锁多次,如果会死锁,就是不可重入锁,如果不会死锁,就是可重入锁

相关面试题:

1) 你是怎么理解乐观锁和悲观锁的,具体怎么实现呢?
悲观锁认为多个线程访问同一个共享变量冲突的概率较大 , 会在每次访问共享变量之前都去真正加锁.
乐观锁认为多个线程访问同一个共享变量冲突的概率不大 . 并不会真的加锁 , 而是直接尝试访问数据. 在访问的同时识别当前的数据是否出现访问冲突 .
悲观锁的实现就是先加锁 ( 比如借助操作系统提供的 mutex), 获取到锁再操作数据 . 获取不到锁就等待.
乐观锁的实现可以引入一个版本号 . 借助版本号识别出当前的数据访问是否冲突 . ( 实现细节参考上面的图).
2) 介绍下读写锁?
读写锁就是把读操作和写操作分别进行加锁 .
读锁和读锁之间不互斥 .
写锁和写锁之间互斥 .
写锁和读锁之间互斥 .
读写锁最主要用在 " 频繁读 , 不频繁写 " 的场景中 .
3) 什么是自旋锁,为什么要使用自旋锁策略呢,缺点是什么?
如果获取锁失败 , 立即再尝试获取锁 , 无限循环 , 直到获取到锁为止 . 第一次获取锁失败 , 第二次的尝试会在极短的时间内到来. 一旦锁被其他线程释放获取到锁
相比于挂起等待锁 ,
优点 : 没有放弃 CPU 资源 , 一旦锁被释放就能第一时间获取到锁 , 更高效 . 在锁持有时间比较短的场景下非常有用.
缺点 : 如果锁的持有时间较长 , 就会浪费CPU资源
4) synchronized 是可重入锁么?
是可重入锁 .
可重入锁指的就是连续两次加锁不会导致死锁 .
实现的方式是在锁中记录该锁持有的线程身份 , 以及一个计数器 ( 记录加锁次数 ). 如果发现当前加锁的线程就是持有锁的线程, 则直接计数自增 .

 二、CAS——compare and swap比较和交换

拿着寄存器/某个内存中的值和另一个内存的值进行比较,如果值相同,就把另一个寄存器/内存的值和当前的这个内存进行交换

假设内存中的原数据V,旧的预期值A,需要修改的值B

1、比较A与V是否相等(比较)

2、如果比较相等,将B写入V(交换)

3、返回操作是否成功

CAS指的是CPU提供了一个单独的CAS指令,通过这一条指令(原子的),就能完成上述过程

由于CAS指令是原子的,可以用来写多线程的代码

CAS如何能解决线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值