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脚本实现.自定义分布式锁注解以及需要注意的问题都没描述.本文就是详细说明如何利用 ...
随机推荐
- SVG (viewBox) & DOM (viewport)
SVG (viewBox) & DOM (viewport) circle "use strict"; /** * * @author xgqfrms * @license ...
- redis源码之dict
大家都知道redis默认是16个db,但是这些db底层的设计结构是什么样的呢? 我们来简单的看一下源码,重要的字段都有所注释 typedef struct redisDb { dict *dict; ...
- 开启算法之路,还原题目,用debug调试搞懂每一道题
文章简述 大家好,本篇是个人的第 3 篇文章. 承接第一篇文章<手写单链表基础之增,删,查!附赠一道链表题>,在第一篇文章中提过,在刷算法题之前先将基础知识过一遍,这样对后面的做算法题是很 ...
- 整合mybatis plus
第一步:导入jar包 导入页面模板引擎,这里我们用的是freemarker <!--mp--> <dependency> <groupId>com.baomidou ...
- 基于docker搭建DNSmasq
一.概述 DNSmasq是一个小巧且方便地用于配置DNS和DHCP的工具,适用于小型网络,它提供了DNS功能和可选择的DHCP功能.它服务那些只在本地适用的域名,这些域名是不会在全球的DNS服务器中出 ...
- Centos7.7下安装Python3.7 并兼容python2.7
前言 1.首先来看一下系统版本 [root@python3 ~]# cat /etc/redhat-release CentOS Linux release 7.7.1810 (Core) 2.更新一 ...
- Mac忘记密码
1.启动电脑的时候,按住 Command+R,直到苹果的图标出现,松开,等待进入... 2.直接点击菜单栏上有个功能里面有 "终端" 功能,点击打开. 3.在终端页面里输入---& ...
- MySQL 多表查询与事务的操作
表连接查询 什么是多表查询 # 数据准备 # 多表查询的作用 * 比如:我们想查询孙悟空的名字和他所在的部门的名字,则需要使用多表查询 # 如果一条 SQL 语句查询多张表,因为查询结果在多张不同的表 ...
- 1.4 数据库和常用SQL语句(正文)——MySQL数据库命令和SQL语句
前面我们已经讲述了,登录时,我们使用mysql –u root –p命令进行,此时如果设置了密码,则需要输入密码. 输入密码后即进入MySQL的操作界面,此时,命令行窗体左侧显示"mysql ...
- Linux目录,rpm及top,vi命令简记
一次简单的Linux常用操作记录 一.一些Linux目录结构 /bin 存放二进制可执行文件(ls.cat.mkdir等),一些常用的命令一般都在这里. /etc 存放系统管理和配置文件 /home ...