多线程之锁机制

多线程之锁机制

1.可重入锁
可重入锁也叫递归锁,指在同一线程中,在外层函数获取到该锁之后,内层的递归函数仍然可以继续获取该锁,在java环境中,reentrantLock和synchronized都是可重入锁,简单来说,就是当某一线程获取了锁之后,仍然可以重复再次获取该锁

2.公平锁与非公平锁
公平锁:指在分配锁前检查是否有线程在排队等待该锁,优先将锁分给等待时间最长的线程,【排队形式的,当排队最前的人可以优先拿锁,没人插队】
非公平锁:指在分配锁使,不考虑线程排队等待的情况,直接尝试获取锁,在获取不到锁时再排队到队尾等待【老阿姨插队,要是能插队了,那就插队,插不了队了,那就骂骂咧咧的去最后排队】
因为公平锁需要在多核的情况下维护一个锁线程等待队列,基于该队列进行锁的分配,因此效率比非公平锁低很多,java中synchronized是非公平锁,reentrantLock默认的lock方法采用的也是非公平锁

3.读写锁
在java中通过lock接口及对象可可以方便的为对象加锁和释放锁,但是这种锁步区分读写,叫作普通锁,为了提高性能,java提供了读写锁,读写锁分为读锁与写锁,多个读锁不互斥,读锁与写锁互斥,在读的地方使用读锁,在写的地方使用写锁,在没有写锁的情况下,读是无阻塞的【类似redis中的读写分离】
如果系统要求共享数据可以同时支持多线程并发读,但不能支持很多线程并发写,那么使用该锁能很大程度的提高效率,如果系统要求共享数据在同一时刻只能有一个线程在写,且在写的过程中不能读取该共享数据,则需要使用写锁
一般的做法是分别定义一个写锁和一个读锁,在读取共享数据时使用读锁,在使用完成后释放读锁,在写共享数据时使用写锁,在使用完成之后释放写锁,在java中通过读写锁的接口ReadWritelock的实现类ReentrantReadWriteLock来完成对读写锁的定义和使用

4.共享锁和独占锁
java并发包提供的加锁模式分为独占锁和共享锁
独占锁:也叫互斥锁,每次只允许一个线程持有该所,ReentrantLock是独占锁
共享锁:允许多个线程同时获取该锁,并发访问共享资源,ReentrantReadWriteLock中的读锁为共享锁
ReentrantReadWriteLock的加锁和解锁操作最终都调用内部类Sync提供的方法,Sync对象通过继承AQS(abstract queued synchronized)进行实现,AQS的内部类Node定义了两个常量shared和exclusive,分别标识AQS队列中等待线程的锁获取模式
独占锁是一种悲观的加锁策略,同一时刻只允许一个读线程读取线程资源,限制了读操作的并发性,因为并发读线程并不会影响数据的一致性,因此共享锁采用了乐观的加锁机制,允许多个执行读操作的线程同时访问共享资源

5.重量级锁和轻量级锁
重量级锁是基于操作系统的互斥量而实现的锁,会导致进程在用户态与内核态之间切换,相对开销较大
synchronized在内部基于监视器锁(monitor)实现,监视器锁基于底层的操作系统的 mutex lock实现,因此synchronized属于重量级锁,因为切换的和开销的原因,所以可以发现synchronized的运行效率并不高
轻量级锁是相对重量级锁而言的,轻量级锁的核心设计是在没有多线程竞争的前提下,减少重量级锁的使用以提高系统性能,轻量级锁适用于线程交替执行同步代码块的情况(即互斥操作),如果同一个时刻有多个线程访问同一个锁,则将会导致轻量级锁膨胀为重量级锁

6.偏向锁
除了在多线程之间存在竞争获取锁的情况,还会经常出现同一个锁被同一个线程多次获取的情况,偏向锁用于某个线程获取某个锁之后,消除这个线程锁重入的开销,看起来似乎是这个线程得到了该锁的偏向
偏向锁的主要目的是在同一个线程多次获取某个锁的情况下尽量减少轻量级锁的执行路径,因为轻量级锁的获取及释放需要多次CAS原子操作,而偏向锁只需要在切换threadID时执行一次CAS原子操作,因此可提高锁的运行效率
在出现多线程竞争锁的情况时,JVM会自动撤销偏向锁,因此偏向锁的撤销操作的耗时必须小于节省下来的CAS原子操作的耗时
由此我们可以发现,轻量级锁用于提高线程交替执行同步块时的性能,偏向锁则在某个线程交替执行同步块时进一步提高性能
锁的状态分为四种:无所,偏向锁、轻量级锁、重量级锁,随着锁竞争越来越激烈,锁可能从偏向一直升级到重量级锁,但是在java中只可以单向升级不可以降级

7.分段锁
分段锁并非一种实际的锁,而是思想,用于将数据分段并在每个分段上都单独加锁把锁进一步细粒度化,以提高并发效率,concurrentHashMap在内部就是使用分段锁实现的

8.同步所与死锁
在有多个线程同时被阻塞时,他们之间相互等待对方释放锁资源,就会出现死锁,为了避免死锁的出现,可以为锁添加超时时间,在线程持有该锁到一定时间之后自动释放

你可能感兴趣的:(多线程之锁机制)