Java锁机制
上一篇简略说了一下Synchronized和Lock,今天就来说一下Java的锁机制。
Java的锁机制主要分为四种,分别是
(1)公平锁、非公平锁
(2)可重入锁
(3)自旋锁 (4)共享锁、独占锁
接下来一一说一下这四种锁
一、公平锁、非公平锁
(1)公平锁:指多个线程按照申请锁的顺序来获取锁,类似于日常的排队
(2)非公平锁:多个线程获取锁的顺序并不是按照申请锁的顺序来,通俗来说就是插队
(3)ReentrantLock默认是非公平的
public ReentrantLock() {
sync = new NonfairSync();
}
也可以是公平的
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
另外,synchronized也是非公平的,非公平的吞吐量比较大
(4)区别:公平锁会维护一个先进先出的线程等待队列,非公平锁是直接获取锁,上去就干,干不过人家再采取公平锁的方式。
公平锁:
非公平锁:
二、可重入锁(又叫递归锁)
(1)是指同一线程外层函数获取锁之后,内层递归函数仍然能持有锁继续运行。
ReentrantLock和synchronized都是可重入锁,比如下面这个demo
static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
first();
}
}).start();
}
}
public static void first() {
lock.lock();
try{
System.out.println(Thread.currentThread().getName()+":11111111111");
Thread.sleep(1000);
second();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void second() {
lock.lock();
try{
System.out.println(Thread.currentThread().getName()+":22222222222");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
运行结果如下:
(2)可重入锁最大的作用就是避免死锁
(3)上一篇也说到了,ReentrantLock可以锁多次,但同样也要释放锁多次。因为锁是有一个状态字段state标明锁状态的,每锁一次就+1,解锁一个就-1,只有状态为0,才是完全解锁。
public static void first() {
lock.lock();
lock.lock();
try{
System.out.println(Thread.currentThread().getName()+":11111111111");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
lock.unlock();
}
}
三、自旋锁
自旋锁在之前解析原子性时就说过了,主要是通过Unsafe+cas实现。
指尝试获取锁的线程不会阻塞,而是采用死循环的方式去尝试获取锁,会消耗大量的cpu
例如:
AtomicReference<Integer> atomicReference = new AtomicReference<>(0);
public void zxLock(){
while (!atomicReference.compareAndSet(0,1)) {
}
}
四、独占锁(写锁)、共享锁
(1)独占锁:指锁在某一时刻只能由一个线程持有,比如ReentrantLock和synchronized。
(2)共享锁:指锁可以同时被多个线程持有。
对于ReentrantReadWriteLock来说,其由ReadLock(写锁)和WriteLock(读锁),其中写锁是独占锁,读锁是共享锁,保证高并发。读写,写读,写写的过程是互斥的。其这些特性可用于缓存机制。
- Python数据科学计算库的安装和numpy简单
- 4G安全:研究人员发现攻击4G无线上网卡和SIM卡的方法
- Python文学化编程 - Jupyter notebook使用和插件拓展
- PoisonCake(毒蛋糕):内置于手机ROM的恶意代码模块
- Spring+SpringMVC+MyBatis整合
- Python之numpy数组学习(五)——广播
- WordPress再悲剧:WPcache-Blogger感染事件影响五万WordPress网站
- 浅谈神经机器翻译
- 窃取Facebook用户信息:利用Android同源策略漏洞的恶意应用被发现
- 关于React Native 安卓首屏白屏优化
- 浅谈spring security 403机制一、无权限访问二、匿名访问三、有权限访问原因机制指定AccessDeniedHandler指定error-page情景原因结论
- Python之numpy数组学习(二)
- Intent 属性详解(上)
- 复仇行动:Notepad++官网被圣战组织黑了
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 【Python基础系列】常见的数据预处理方法(附代码)
- 机器学习基础:类别不平衡问题处理方法汇总及实际案例解析
- 机器学习与统计学:R方代表什么?和P值的关系是什么?
- 机器学习基础:缺失值的处理技巧(附Python代码)
- 七夕限定,致程序员的专属浪漫
- 使用 Docker Multi-stage 高效构建镜像
- vue(typescript) 使用webpack-bundle-analyzer
- 2020年学习Python-爬取百度图片
- 自动化运维 | Ansible lookup
- 【TBase开源版测评】Hello, TBase
- linux定位问题常用命令
- 聊聊claudb的zset command
- 腾讯云语音识别v1签名算法详解
- MySQL案例:关于JSON的一个bug
- Confluence 如何查看页面树