锁相关

ReentrantLock和synchronized区别

1)synchronized是独占锁,加锁和解锁的过程自动进行,易于操作,但不够灵活。ReentrantLock也是独占锁,加锁和解锁的过程需要手动进行,不易操作,但非常灵活。

2)synchronized可重入,因为加锁和解锁自动进行,不必担心最后是否释放锁;ReentrantLock也可重入,但加锁和解锁需要手动进行,且次数需一样,否则其他线程无法获得锁。

3)synchronized不可响应中断,一个线程获取不到锁就一直等着;ReentrantLock可以响应中断(tryLock方法:获取不到锁则返回false)。

4)synchronized不具备设置公平锁的特点,ReentrantLock可以成为公平锁。

ReentrantReadWriteLock适用什么业务场景?有什么特点?

适用于读多,写少业务场景;

1). 写写不可并发
2). 读写不可并发/写读不可并发
3). 读读可以并发

读写锁允许同一时刻被多个读线程访问,但是在写线程访问时,所有的读线程和其他的写线程都会被阻塞。

支持公平/非公平策略

支持可重入
	- 同一读线程在获取了读锁后还可以获取读锁
	- 同一写线程在获取了写锁之后既可以再次获取写锁又可以获取读锁
	- 同一读线程在获取了读锁后[不可以]获取写锁
	
在读线程非常多,写线程很少的情况下,很容易导致写线程“饥饿”,虽然使用“公平”策略可以一定程度上缓解这个问题,但是“公平”策略是以牺牲系统吞吐量为代价的。	

什么是CAS?说说优缺点?

CAS,即Compare-And-Swap,是一种用于多线程编程中的同步原语。它的主要作用是在并发环境下保证数据的一致性和线程安全。

CAS操作包含三个基本步骤:比较、交换和返回结果。

CAS的优点

	高效性:CAS操作通常比锁机制更轻量级,因为它避免了线程阻塞和上下文切换的开销。在多核处理器上,CAS可以显著提高性能,因为它减少了锁竞争和等待时间。

	非阻塞性:由于CAS是非阻塞的,多个线程可以同时尝试更新同一个变量,而不会导致死锁或活锁的问题。这使得系统能够更好地利用多核处理器的能力,提高了并行度和吞吐量。

	简化代码:使用CAS可以减少显式的锁管理,从而简化代码逻辑,使代码更加简洁易读。开发者不需要担心锁的获取和释放,也不需要处理锁的细粒度控制问题。

	避免死锁:CAS操作不会导致死锁,因为它不会持有任何锁,也不会阻塞其他线程。这降低了系统的复杂性,减少了潜在的错误和风险。

	适用于简单场景:对于简单的数据结构和操作,CAS是一种非常有效的同步机制。它可以快速地检查和更新共享变量的值,而无需额外的同步措施。

CAS的缺点

	ABA问题:当一个线程读取变量的值并准备更新时,另一个线程可能已经修改了该值并重新写回了原值,导致CAS操作误认为没有发生变化。这种情况称为ABA问题(A-B-A),它会引发竞态条件,导致数据不一致。

	循环时间长开销大:自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。因为线程会不断地进行CAS操作,直到成功为止,这可能导致CPU资源的浪费和性能下降。

	只能保证一个共享变量的原子操作:当对多个共享变量进行原子操作时,循环CAS无法保证其原子性。这意味着在复杂的操作中,可能需要额外的同步机制来确保数据的一致性。

	适用场景有限:CAS主要适用于简单的同步场景,对于复杂的操作和数据结构,可能需要使用更高级的同步机制。例如,在涉及多个变量的操作中,CAS可能无法提供足够的原子性和一致性保证。

	可能导致性能下降:在高争用的环境中,大量的线程可能会频繁地进行CAS操作,导致CPU缓存行失效和内存带宽的消耗。这可能会降低系统的性能,尤其是在多核处理器上。

总的来说,CAS是一种强大的工具,它在适当的场景下可以提供高效的并发控制。然而,开发者需要谨慎使用CAS,以避免潜在的问题和陷阱。在选择是否使用CAS时,应考虑具体的应用场景、性能要求以及系统的复杂性。

AQS的底层原理?

AQS使用一个volatile成员变量state来表示锁是否已被持有,通过内置的FIFO队列存储被阻塞的线程。

AQS使用CAS机制对state进行原子操作从而对state的值进行修改。

如果state的值为0,表示锁未被持有,则将当前线程设置为工作线程(即获取到了锁),并将state的值设置为1,返回成功获取到锁。

如果未能成功获取到锁,AQS先自旋获取锁,如果一直获取不到,则将当前获取不到锁的线程加入到FIFO队列中

说说synchronized锁升级过程?

- 无锁状态:没有线程来申请锁

- 偏向锁状态:只有一个线程来申请锁,【没有竞争】,不需要做加锁、解锁的操作

  - 从无锁状态到当前状态,每次来申请锁的都是这同一个线程,中间没有别的线程来申请过
  
- 轻量级锁状态:只有一个线程来申请锁,【没有竞争】,不需要做加锁、解锁的操作

  - 从上一个状态到现在状态,锁对象被不同线程申请过,只不过每次都是只有一个线程来申请
  
- 重量级锁状态:同时有多个线程来申请锁,【有竞争】,需要做加锁、解锁的操作
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计