多线程 锁策略 ( 悲观/乐观锁 读写/互斥锁 重量/轻量级锁挂起等待/自旋锁 公平/非公平锁 可重入/不可重入锁)
Posted Perceus
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程 锁策略 ( 悲观/乐观锁 读写/互斥锁 重量/轻量级锁挂起等待/自旋锁 公平/非公平锁 可重入/不可重入锁)相关的知识,希望对你有一定的参考价值。
@TOC
一、常见的锁策略
1. 悲观锁 VS 乐观锁
悲观锁 :
就是它认为,只要它一加锁,就会出现锁冲突。
乐观锁:
就是说:它加锁没有那么容易就会出现锁冲突。
思考一个问题:
悲观锁的事情做得多
举例:
分析:
2. 读写锁 vs 普通的互斥锁
==只要两个线程对同一个对象加锁,就会产生互斥==
对于读写锁
,就相当于将 读锁 和 写锁 给分开了
。
分开了有什么好处呢 ?
读写锁在Java 标准库提供了 ReentrantReadWriteLock 类, 实现了读写锁.
-
ReentrantReadWriteLock.ReadLock 类
表示一个读锁
. 这个对象提供了lock / unlock
方法进行加锁解锁. ReentrantReadWriteLock.WriteLock 类
表示一个写锁
. 这个对象也提供了lock / unlock
方法进行加锁解锁.
3. 重量级锁 vs 轻量级锁
这个两个锁 和 上面的悲观乐观两个锁,含义上有一定的重叠。
重量级锁就是做了更多的事情,开销很大。
轻量级锁,做的事情很少,开销也就很小。
更具体的来说:
4. 挂起等待锁 vs 自旋锁
挂起等待锁:
往往就是通过内核的一些机制来实现的
,往往较重
[重量级锁的一种典型实现]自旋锁
:往往是通过用户态代码来实现的
,往往较轻
[轻量级锁的一种典型实现]
==理解自旋锁 vs 挂起等待锁==
小结
5. 公平锁 VS 非公平锁
这俩可能有点容易搞反,要记住
对于操作系统来说,本身线程之间的调度就是随机的(机会均等)
,操作系统提供的mutex这个锁,就属于非公平锁
线程之间不是存在优先级嘛?优先级难道不会影响调度吗?
6. 可重入锁 和 不可重入锁
重入锁实现
理解 “把自己锁死”
一个线程没有释放锁, 然后又尝试再次加锁
// 第一次加锁, 加锁成功
lock();
// 第二次加锁, 锁已经被占用, 阻塞等待.
lock();
例子:
一个人闪现进了上锁的厕所,里面出不去,外面进不来
synchronized 与 锁策略的对应关系
谈谈常用的synchronized这把锁:
二、相关面试题
1. 你是怎么理解乐观锁和悲观锁的,具体怎么实现呢?
2. 介绍下读写锁?
3. 什么是自旋锁,为什么要使用自旋锁策略呢,缺点是什么?
相比于挂起等待锁优点:
缺点:
4. synchronized 是可重入锁么?
是可重入锁.
举例:
public class Xttblog extends SuperXttblog
public static void main(String[] args)
Xttblog child = new Xttblog();
child.doSomething();
public synchronized void doSomething()
System.out.println("child.doSomething()" + Thread.currentThread().getName());
doAnotherThing(); // 调用自己类中其他的synchronized方法
private synchronized void doAnotherThing()
super.doSomething(); // 调用父类的synchronized方法
System.out.println("child.doAnotherThing()" + Thread.currentThread().getName());
class SuperXttblog
public synchronized void doSomething()
System.out.println("father.doSomething()" + Thread.currentThread().getName());
结果:
child.doSomething()Thread-5492
father.doSomething()Thread-5492
child.doAnotherThing()Thread-5492
还看不懂?那我就再解释下!
以上是关于多线程 锁策略 ( 悲观/乐观锁 读写/互斥锁 重量/轻量级锁挂起等待/自旋锁 公平/非公平锁 可重入/不可重入锁)的主要内容,如果未能解决你的问题,请参考以下文章