各种锁的理解

公平锁、非公平锁

公平锁:先到先得(不可插队)

非公平锁:达者为先(可插队)---------->默认

public ReentrantLock() {
//默认非公平锁
sync = new NonfairSync();
}
//重载的构造方法,通过fair控制是否公平
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
可重入锁(递归锁)

所有的锁都是可重入锁

Synchronized版

package org.example.lock;

public class Demo01 {
public static void main(String[] args) {
phone1 p1 = new phone1();
new Thread(()->{
p1.ems();
},"A").start();
new Thread(()->{
p1.ems();
},"B").start();
}
}
class phone1{
public synchronized void ems(){
System.out.println(Thread.currentThread().getName()+"---------->ems");
call();
}
public synchronized void call(){
System.out.println(Thread.currentThread().getName()+"---------->call");
}
}

ems方法中包含了call方法,所以当我们调用ems方法获取到锁时,也把call方法的synchronized锁获取到了。

错误理论

  • 当线程A运行ems方法后运行call方法时ems锁释放,线程B可以获取到ems方法

正确理论

  • 当线程A运行ems方法后运行call方法时ems方法的锁还未释放时就拿到了call方法中的锁,当call方法的锁释放后ems方法的锁才会释放。线程B此时就可以运行ems方法了

Lock版

package org.example.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class Demo02 {
public static void main(String[] args) {
phone2 p2 = new phone2();
new Thread(()->{
p2.ems();
},"A").start();
new Thread(()->{
p2.ems();
},"B").start();
}
}
class phone2{
Lock lock = new ReentrantLock();
public void ems(){
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"---------->ems");
call();
} catch (Exception e) {
e.printStackTrace();
} finally {
//等待call方法锁解锁后再解锁
lock.unlock();
} }
public void call(){
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"---------->call");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
} }
}
自旋锁

spinlock(不断尝试直至成功)

已经见过了,就是unsafe中的自增getAndAddInt方法中的do-while循环就是一把自旋锁

自己写一把锁

package org.example.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; public class SpinLockDemo {
//int 0
//Thread null
public static AtomicReference<Thread> atomic = new AtomicReference<>(); public static void lock(){
Thread thread = Thread.currentThread();
System.out.println("===============>"+thread.getName()+"===========>lock");
//自旋锁,若线程等于null,则compareAndSet为true,加!就为false,就会一直循环
while (!atomic.compareAndSet(null,thread)){ }
}
public static void unlock(){
Thread thread = Thread.currentThread();
System.out.println("===============>"+thread.getName()+"===========>unlock");
//自旋锁
atomic.compareAndSet(thread,null);
} public static void main(String[] args) throws InterruptedException {
new Thread(()->{
try {
lock();
TimeUnit.SECONDS.sleep(10);
} catch (Exception e) {
e.printStackTrace();
} finally {
unlock();
}
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
try {
lock();
TimeUnit.SECONDS.sleep(2);
} catch (Exception e) {
e.printStackTrace();
} finally {
unlock();
}
},"B").start();
}
}
死锁

死锁是什么

死锁测试

package org.example.lock;

import java.util.concurrent.TimeUnit;

public class DeadLockDemo {
public static void main(String[] args) {
String a = "A";
String b = "B";
new Thread(()->{new MyThread(a, b).run();},"A").start();
new Thread(()->{new MyThread(b, a).run();},"B").start();
}
}
class MyThread implements Runnable{
private String lockA;
private String lockB; public MyThread(String lockA, String lockB) {
this.lockA = lockA;
this.lockB = lockB;
} @Override
public void run() {
synchronized (lockA){
System.out.println(Thread.currentThread().getName()+"lock:"+lockA+"=>get"+lockB);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (lockB){
System.out.println(Thread.currentThread().getName()+"lock:"+lockB+"=>get"+lockA);
}
}
}
}

程序突然卡住死锁如何排查?

1、使用jps-l定位进程号

查看当前java活着的进程

2、使用jstack 进程号查看死锁问题

查找到一个死锁问题!

面试或者工作中排查问题:

1、查看异常

2、查看日志

3、查看堆栈信息

JUC并发编程(终章)各种锁的理解的更多相关文章

  1. JUC并发编程基石AQS之主流程源码解析

    前言 由于AQS的源码太过凝练,而且有很多分支比如取消排队.等待条件等,如果把所有的分支在一篇文章的写完可能会看懵,所以这篇文章主要是从正常流程先走一遍,重点不在取消排队等分支,之后会专门写一篇取消排 ...

  2. Java并发编程实战 03互斥锁 解决原子性问题

    文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...

  3. JUC并发编程学习笔记

    JUC并发编程学习笔记 狂神JUC并发编程 总的来说还可以,学到一些新知识,但很多是学过的了,深入的部分不多. 线程与进程 进程:一个程序,程序的集合,比如一个音乐播发器,QQ程序等.一个进程往往包含 ...

  4. Python并发编程-GIL全局解释器锁

    Python并发编程-GIL全局解释器锁 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.GIL全局解释器锁概述 CPython 在解释器进程级别有一把锁,叫做GIL,即全局解释 ...

  5. java并发编程--第一章并发编程的挑战

    一.java并发编程的挑战 并发编程需要注意的问题: 并发编程的目的是让程序运行的更快,然而并不是启动更多的线程就能让程序最大限度的并发执行.若希望通过多线程并发让程序执行的更快,会受到如下问题的挑战 ...

  6. Pthread 并发编程(二)——自底向上深入理解线程

    Pthread 并发编程(二)--自底向上深入理解线程 前言 在本篇文章当中主要给大家介绍线程最基本的组成元素,以及在 pthread 当中给我们提供的一些线程的基本机制,因为很多语言的线程机制就是建 ...

  7. JUC并发编程基石AQS源码之结构篇

    前言 AQS(AbstractQueuedSynchronizer)算是JUC包中最重要的一个类了,如果你想了解JUC提供的并发编程工具类的代码逻辑,这个类绝对是你绕不过的.我相信如果你是第一次看AQ ...

  8. JUC : 并发编程工具类的使用

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.JUC是什么 1.JUC定义 JUC,即java.util.concurrent 在并发编程中使用的 ...

  9. JUC并发编程与高性能内存队列disruptor实战-上

    JUC并发实战 Synchonized与Lock 区别 Synchronized是Java的关键字,由JVM层面实现的,Lock是一个接口,有实现类,由JDK实现. Synchronized无法获取锁 ...

  10. JUC并发编程详解(通俗易懂)

    一.JUC简介 在Java5.0提供了java.util.concurrent包,简称JUC,即Java并发编程工具包.JUC更好的支持高并发任务. 具体的有以下三个包: java.util.conc ...

随机推荐

  1. asp.net core之Host

    Host简介 在ASP.NET Core中,Host是一个托管应用程序的宿主环境.它提供了一种统一的方式来启动和运行应用程序,无论是在开发环境中还是在生产环境中.Host负责处理应用程序的生命周期.配 ...

  2. VuePress@next 使用数学公式插件

    VuePress@next 使用数学公式插件 搞了一个VuePress1.0的 现在升级了一下,但是使用数学公式的插件老报错啊!经过不懈努力,终于搞定了.现在记录一下. VuePress 介绍 Vue ...

  3. 王道oj/problem23

    网址:oj.lgwenda.problem/23 代码: #define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include<stri ...

  4. python3使用ESL和sipp自动多轮压测FreeSWITCH

    环境:CentOS 7.6_x64   FreeSWITCH版本 :1.10.9   sipp版本:3.6.1   python版本:3.9.12 日常工作中,有时会遇到批量自动压测FreeSWITC ...

  5. 绕过网站CDN查找网站真实ip方法大全(持续更新中)

    这是一篇全网(无论国内还是国外)最全.最详细.最新.最实用的关于 CDN 网络对抗攻击的文章,渗透测试中若碰到 CDN 类的问题,只需要看这一篇指南即可.我也会在 Github (https://gi ...

  6. MySQL配置简单优化与读写测试

    测试方法 先使用sysbench对默认配置的MySQL单节点进行压测,单表数据量为100万,数据库总数据量为2000万,每次压测300秒. sysbench --db-driver=mysql --t ...

  7. 让C#调用vue组件里的方法

    前言:web页面开发时采用的是vue开发的,后台语言是C# 需求:后台需要通过浏览器调用vue组件的方法 c# 可以调用xxx.html 中的script引用的js中定义的方法是可以调用的, 之前c# ...

  8. 2023-09-01:用go语言编写。给出两个长度均为n的数组, A = { a1, a2, ... ,an }, B = { b1, b2, ... ,bn }。 你需要求出其有多少个区间[L,R]

    2023-09-01:用go语言编写.给出两个长度均为n的数组, A = { a1, a2, ... ,an }, B = { b1, b2, ... ,bn }. 你需要求出其有多少个区间[L,R] ...

  9. 在线问诊 Python、FastAPI、Neo4j — 创建症状节点

    目录 症状数据 创建节点 附学习 电子病历中,患者主诉对应的相关检查,得出的诊断以及最后的用药情况.症状一般可以从主诉中提取. 症状数据 symptom_data.csv CSV 中,没有直接一行一个 ...

  10. MySQL系列2:InnoDB存储引擎

    1. 架构回顾 上一篇我们讲解了MySQL的逻辑架构,重新回顾一下,用一张新的图来认识一下该架构. 整体架构分为service层与存储引擎层,请求交给连接池后,由后台线程处理,并将请求转发给SQL接口 ...