java面试-公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解
一、公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解
公平锁:多个线程按照申请的顺序来获取锁。
非公平锁:多个线程获取锁的先后顺序与申请锁的顺序无关。【ReentrantLock 默认非公平、synchronized】
总结:非公平锁的吞吐量比公平锁大。
可重入锁(又名递归锁):线程可以进入任何一个它已经获取锁的同步代码块中。
可重入锁的最大作用:避免死锁
自旋转:是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁。
好处:减少线程上下文切换的消耗,
缺点:循环会消耗CPU
二、请手写一个自旋锁
/**
* Created by wujuhong on 2019/1/14.
* 通过AtomicReference可实现简单的自旋
*/
public class SpinLock { //原子引用线程
private AtomicReference<Thread> atomicReference = new AtomicReference<>(); //让当前想要获取锁的线程做几个空循环
public void mylock() {
Thread currentThread = Thread.currentThread();
System.out.println(Thread.currentThread().getName()+" come in");
while (!atomicReference.compareAndSet(null, currentThread)) { }
} public void myunlock() {
Thread currentThread = Thread.currentThread();
atomicReference.compareAndSet(currentThread, null);
System.out.println(Thread.currentThread().getName()+" invoked myunlock"); } public static void main(String[] args) {
SpinLock spinLock = new SpinLock();
new Thread(() -> {
spinLock.mylock(); try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLock.myunlock();
},"AA").start(); try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} new Thread(() -> {
spinLock.mylock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLock.myunlock();
},"BB").start(); }
}
三、ReentrantReadWriteLock读写锁
- 允许多个线程同时读共享变量
- 只允许一个线程写共享变量
- 如果一个写线程正在执行写操作,此时禁止读线程读共享变量
说明:锁升级不允许,锁降级允许
public class ReadWriteLockDemo {
//写操作:原子+独占,整个过程必须是一个完整的统一体,中间不许被分割,被打断。
public static void main(String[] args) {
MyCache myCache = new MyCache();
for (int i = 0; i <= 5; i++) {
final int tempInt = i;
new Thread(() -> myCache.put(tempInt + "", tempInt), String.valueOf(i)).start();
}
for (int i = 0; i <= 5; i++) {
final int tempInt = i;
new Thread(() -> myCache.get(tempInt + ""), String.valueOf(i)).start();
}
}
}
class MyCache {
private volatile Map<String, Object> map = new HashMap<>();
private ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();
public void put(String key, Object value) {
rwlock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 正在写入" + key);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(key, value);
System.out.println(Thread.currentThread().getName() + " 写入完成");
} finally {
rwlock.writeLock().unlock();
}
}
public void get(String key) {
rwlock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 正在读取");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object result = map.get(key);
System.out.println(Thread.currentThread().getName() + " 读取完成" + result);
} finally {
rwlock.readLock().unlock();
}
}
}
java面试-公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解的更多相关文章
- 最全Java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁
在Java并发场景中,会涉及到各种各样的锁如公平锁,乐观锁,悲观锁等等,这篇文章介绍各种锁的分类: 公平锁/非公平锁 可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 自旋锁 01.乐观锁 vs 悲观 ...
- Java锁--非公平锁
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3496651.html 参考代码 下面给出Java1.7.0_40版本中,ReentrantLock和AQ ...
- Java中的常见锁(公平和非公平锁、可重入锁和不可重入锁、自旋锁、独占锁和共享锁)
公平和非公平锁 公平锁:是指多个线程按照申请的顺序来获取值.在并发环境中,每一个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个就占有锁,否者就会加入到等待队列中,以 ...
- ReentrantLock可重入锁、公平锁非公平锁区别与实现原理
ReentrantLock是lock接口的一个实现类,里面实现了可重入锁和公平锁非公平锁 ReentrantLock公平锁和不公平锁实现原理 公平锁会获取锁时会判断阻塞队列里是否有线程再等待,若有获取 ...
- “全栈2019”Java多线程第二十九章:可重入锁与不可重入锁详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析
原文:Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析 一.RedissonLock#lock 源码分析 1.根据锁key计算出 slot,一个slot对 ...
- Java最全锁剖析:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁
乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度,在Java和数据库中都有此概念对应的实际应用. 1.乐观锁 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会 ...
- Java 多线程 -- 理解锁:手动实现可重入锁和不可重入锁
JDK提供的大多数内置锁都是可重入的,也就是 说,如果某个线程试图获取一个已经由它自己持有的锁时,那么这个请求会立 刻成功,并且会将这个锁的计数值加1,而当线程退出同步代码块时,计数器 将会递减,当计 ...
- 【分布式锁】Redis实现可重入的分布式锁
一.前言 之前写的一篇文章<细说分布式锁>介绍了分布式锁的三种实现方式,但是Redis实现分布式锁关于Lua脚本实现.自定义分布式锁注解以及需要注意的问题都没描述.本文就是详细说明如何利用 ...
随机推荐
- nodejs ECMAScript 模块
node 文档 main.mjs import path from 'path'; import logger from './logger.js'; logger.show('hello world ...
- Flutter: 监听App显示,隐藏
关键代码 class _MyAppState extends State<MyApp> with WidgetsBindingObserver { @override void initS ...
- [JAVA学习笔记]JAVA基本程序设计结构
一个简单的Java应用程序 public class FirstSample { public static void main(String[] args) { System.out.println ...
- .net实现filestream类复制文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...
- MongoDB语句命令
更新列名 db.xx.update({}, {$rename : {"StoreId" : "MetaId"}}, false, true) 查询长度 db.g ...
- 🎊 Element UI 新春快报
新年好,Element UI 开发团队给各位支持我们的开发者们拜个晚年,祝大家在新的一年里工作没 bug, 天天不加班. 在过去一年里,Element UI 团队在稳定维护 Vue 2.x 版本的同时 ...
- C语言:试探算法解决“八皇后”问题
#include <stdio.h> #define N 4 int solution[N], j, k, count, sols; int place(int row, int col) ...
- Elasticsearch常用API
Note:以下API基于ES 5x,6x/7x可能略有不同,具体查看官方文档 ES常用API # 查看集群node curl "http://localhost:9200/_cat/node ...
- 《从零开始TypeScript》系列 - 基础数据类型
TypeScript 是 JavaScript 的超集,这里我们只讨论两者中的不同的部分,或者需要注意的部分 数组 Array:在TypeScript中,有两种方式来定义一个数组: 在元素类型后面接上 ...
- solr 远程代码执行(CVE-2019-12409)
Apache Solr 远程代码执行漏洞(CVE-2019-12409) 简介 Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口.是apache的顶级开源项 ...