一、公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解

公平锁:多个线程按照申请的顺序来获取锁。

非公平锁:多个线程获取锁的先后顺序与申请锁的顺序无关。【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面试-公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解的更多相关文章

  1. 最全Java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

    在Java并发场景中,会涉及到各种各样的锁如公平锁,乐观锁,悲观锁等等,这篇文章介绍各种锁的分类: 公平锁/非公平锁 可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 自旋锁 01.乐观锁 vs 悲观 ...

  2. Java锁--非公平锁

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3496651.html 参考代码 下面给出Java1.7.0_40版本中,ReentrantLock和AQ ...

  3. Java中的常见锁(公平和非公平锁、可重入锁和不可重入锁、自旋锁、独占锁和共享锁)

    公平和非公平锁 公平锁:是指多个线程按照申请的顺序来获取值.在并发环境中,每一个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个就占有锁,否者就会加入到等待队列中,以 ...

  4. ReentrantLock可重入锁、公平锁非公平锁区别与实现原理

    ReentrantLock是lock接口的一个实现类,里面实现了可重入锁和公平锁非公平锁 ReentrantLock公平锁和不公平锁实现原理 公平锁会获取锁时会判断阻塞队列里是否有线程再等待,若有获取 ...

  5. “全栈2019”Java多线程第二十九章:可重入锁与不可重入锁详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  6. Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析

    原文:Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析 一.RedissonLock#lock 源码分析 1.根据锁key计算出 slot,一个slot对 ...

  7. Java最全锁剖析:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

    乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度,在Java和数据库中都有此概念对应的实际应用. 1.乐观锁 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会 ...

  8. Java 多线程 -- 理解锁:手动实现可重入锁和不可重入锁

    JDK提供的大多数内置锁都是可重入的,也就是 说,如果某个线程试图获取一个已经由它自己持有的锁时,那么这个请求会立 刻成功,并且会将这个锁的计数值加1,而当线程退出同步代码块时,计数器 将会递减,当计 ...

  9. 【分布式锁】Redis实现可重入的分布式锁

    一.前言 之前写的一篇文章<细说分布式锁>介绍了分布式锁的三种实现方式,但是Redis实现分布式锁关于Lua脚本实现.自定义分布式锁注解以及需要注意的问题都没描述.本文就是详细说明如何利用 ...

随机推荐

  1. SVG (viewBox) & DOM (viewport)

    SVG (viewBox) & DOM (viewport) circle "use strict"; /** * * @author xgqfrms * @license ...

  2. redis源码之dict

    大家都知道redis默认是16个db,但是这些db底层的设计结构是什么样的呢? 我们来简单的看一下源码,重要的字段都有所注释 typedef struct redisDb { dict *dict; ...

  3. 开启算法之路,还原题目,用debug调试搞懂每一道题

    文章简述 大家好,本篇是个人的第 3 篇文章. 承接第一篇文章<手写单链表基础之增,删,查!附赠一道链表题>,在第一篇文章中提过,在刷算法题之前先将基础知识过一遍,这样对后面的做算法题是很 ...

  4. 整合mybatis plus

    第一步:导入jar包 导入页面模板引擎,这里我们用的是freemarker <!--mp--> <dependency> <groupId>com.baomidou ...

  5. 基于docker搭建DNSmasq

    一.概述 DNSmasq是一个小巧且方便地用于配置DNS和DHCP的工具,适用于小型网络,它提供了DNS功能和可选择的DHCP功能.它服务那些只在本地适用的域名,这些域名是不会在全球的DNS服务器中出 ...

  6. Centos7.7下安装Python3.7 并兼容python2.7

    前言 1.首先来看一下系统版本 [root@python3 ~]# cat /etc/redhat-release CentOS Linux release 7.7.1810 (Core) 2.更新一 ...

  7. Mac忘记密码

    1.启动电脑的时候,按住 Command+R,直到苹果的图标出现,松开,等待进入... 2.直接点击菜单栏上有个功能里面有 "终端" 功能,点击打开. 3.在终端页面里输入---& ...

  8. MySQL 多表查询与事务的操作

    表连接查询 什么是多表查询 # 数据准备 # 多表查询的作用 * 比如:我们想查询孙悟空的名字和他所在的部门的名字,则需要使用多表查询 # 如果一条 SQL 语句查询多张表,因为查询结果在多张不同的表 ...

  9. 1.4 数据库和常用SQL语句(正文)——MySQL数据库命令和SQL语句

    前面我们已经讲述了,登录时,我们使用mysql –u root –p命令进行,此时如果设置了密码,则需要输入密码. 输入密码后即进入MySQL的操作界面,此时,命令行窗体左侧显示"mysql ...

  10. Linux目录,rpm及top,vi命令简记

    一次简单的Linux常用操作记录 一.一些Linux目录结构 /bin 存放二进制可执行文件(ls.cat.mkdir等),一些常用的命令一般都在这里. /etc 存放系统管理和配置文件 /home ...