常见的锁及其应用场景;
锁名称 | 应用 |
---|---|
乐观锁 | CAS |
悲观锁 | Synchronized、Vector、Hashtable |
自旋锁 | CAS |
可重入锁 | Synchronized、ReetrantLook、Lock |
读写锁 | ReetrantReadWriterLock、copyOnWriterArrayList、CopyOnWriterArraySet |
公平锁 | ReetrantLock(True) |
非公平锁 | Synchronized、ReetrantLock(false) |
重量级锁 | Synchronized |
轻量级锁 | 锁优化技术 |
偏向锁 | 锁优化技术 |
分段锁 | ConcurrentHashMap |
互斥锁、同步锁 | Synchronized |
死锁 | 相互请求资源 |
锁消除 | 锁优化技术 |
锁粗化 | 锁优化技术 |
常见锁的解释
乐观锁:
- 乐观锁是一种乐观思想,假定当前环境是读多写少,遇到的并发写的情况比较低,读取数据时认为别的线程不会正在修改(所以没有上锁),写数据时,判断当前与期望值是否相同,如果相同则进行更新(更新期间加锁,保证是原子性的)(CAS)
- java中的乐观锁:CAS比较与替换,比较当前值(主内存中的值),与预期值(当前线程中的值,之内存中值的一份拷贝)是否一样,一样就更新,否则继续进行CAS.
-
悲观锁
- 悲观锁是一种悲观思想,认为当前环境是写多读少,遇到并发写的可能性很高,每次去拿数据的时候都认为其他线程会修改,所以每次读写都会认为其他线程会修改,所以每次读写都会上锁
- Java中的悲观锁:synchronized修饰的方法和方法块、ReetrantLook
-
自旋锁
- 自旋锁是一种技术:为了让线程等待,我们只只需让线程执行一个忙循环(自旋),能让俩个以上的线程同时并行执行,就可以让后面请求锁的那个线程多“等待一会”,但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁。
- 自旋锁的优点:避免了线程切换的开销(避免了线程上下文的切换),挂起和恢复线程的操作都需要转入内核态中完成,这些操作给jvm的并发性带来了压力。
- 自旋锁的缺点:占用处理器时间,如果占用时间太长,会白白消耗处理器资源,不会做任何有价值的工作,所以自旋等待的时间一定要有一个限度
- 自旋默认的次数是:10次,可以自行更改。
-
可重入锁
- 可重入锁是一种技术,任一线程在获取到锁之后能够再次获取该锁而不会被锁阻塞。
- 原理:如果当前获取锁的线程是否为当前占据锁的线程,如果是,则再次成功获取锁,进行计数+1。释放锁:释放锁时,记性计数-1.
- 注意:可重入锁只能解决或许同一锁的死锁问题。面对的是同一把锁的可重入问题。
- 获取了多把锁但没有全部释放掉会导致层序卡死,线程出不来。
- 获取了n把锁但释放了n+1把锁程序会报错。
-
读写锁
- 读写锁是一种技术,通过ReetrantReadWriterLock类来实现,为了提高性能,java提供了读写锁,在读的地方使用读锁,写的地方使用写锁。读是没有阻塞的,多个读锁不互斥,读锁和写锁互斥,这是由JVm自己控制的。
- 读锁:允许多个线程获取读锁,同时访问同一资源。
- 写锁:只允许一个线程或许写锁,不允许同时访问同一资源。
-
公平锁:
- 公平锁是一种思想:多个线程按照申请的锁的顺序来获取锁。
- 该锁会维护一个等待队列,每个线程会查看每个锁的等待队列,如果等待队列为空,就获取锁,如果不为空就放入队列末尾,按照FIFO的原则从队列拿到线程,然后占有锁。
-
非公平锁:
- 非公平锁是一种思想,多个线程获取锁,不是先来的先得到锁,谁抢上谁就拥有锁。
- 优点:非公平锁的性能高于公平锁。
- 缺点:有可能某个线程长时间获取不到锁。
-
共享锁和独占锁
- 共享锁:以共享的方式持有锁,和乐观锁读写锁一样。
- 独占锁:只能有一个线程获取锁,和悲观锁和互斥锁同意。
-
重量级锁:
- 重量级锁是一种称谓:sysnchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的,监视器本身依赖底层的操作系统的Mutex Lock(互斥锁)来实现的,操作系统实现线程的切换需要从用户态到核心态,成本非常高,这种依赖于操作系统Mutex Lock来实现锁的称为重量级锁,为了优化synchronized,引入了轻量级锁和偏向锁。
-
轻量级锁:
- 轻量级锁是一种锁的优化机制,是指在没有产生竞争的情况下使用CAS操作去消除同步使用的互斥量,就是说如果线程之间没有产生竞争的关系,就不需要用户态到内核态的频繁切换,可以提升性能。
- 如果出现俩个以上的线程共同竞争一把锁,就会导致线程无休止的自旋,导致cpu资源的浪费,当到达一定的自旋次数就会将此线程阻塞并挂起,等待被唤醒。
- 如果出现了竞争并且不升级为重量锁的话,轻量级锁会比重量级锁更慢。
-
偏向锁
- 没有与当前线程竞争的情况,就是说该锁只有被这一个线程来回获取就是偏向锁。
- 偏向锁也是一种优化机制。
-
互斥锁:
- 互斥锁和乐观锁和读锁有不同点,读锁是多个线程都可以读取数据,而互斥锁任和情况下也能单个线程就能访问。和悲观锁和独占锁同意。
-
同步锁
- 同步锁和互斥锁同义,在并发情况下执行的多个线程,在同一时间只允许一个线程访问共享数据。
-
锁粗化
- 锁粗化是一种优化技术,如果一系列的操作都是对同义操作进行的反复加锁和解锁,造成性能的消耗,一种解决方案是将锁的范围扩大化到整个序列的外部,这样加锁的频率就是大大降低。减少性能消耗。
CAS
CAS的全称叫做 CompareAndSwap--比较与交换,是一种轻量级的同步机制,主要用于在多线程下的无锁算法和数据结构,保证了并发安全性,他可以在不适用锁的情况下,对共享数据进行线程安全的操作。(下图仅做参考)