JUC(11)各种锁的理解(公平锁、可重入锁、自旋锁、死锁)

简介: 这篇文章介绍了Java并发包中的各种锁机制,包括公平锁与非公平锁、可重入锁、自旋锁以及死锁的概念、实现和示例,以及如何使用jps和jstack工具来检测和诊断死锁问题。

文章目录

  • 1、公平锁、非公平锁
  • 2、可重入锁
  • 3、自旋锁
  • 4、死锁

1、公平锁、非公平锁

公平锁:非常公平、不能插队、必须先来后到

  • 非公平锁:非常不公平、可以插队、(默认非公平)
    在这里插入图片描述
    可以修改为公平锁
    在这里插入图片描述

2、可重入锁

拿到外边的锁、就会自动拿到里边的锁。

package com.lock;

/**
 * synchronized
 */
public class Demo1 {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(()->{
            phone.sms();
        },"A").start();

        new Thread(()->{
            phone.sms();
        },"B").start();
    }
}

class Phone{

    public synchronized void sms(){
        System.out.println(Thread.currentThread().getName()+"sms");
        call();
    }

    public synchronized  void call(){
        System.out.println(Thread.currentThread().getName()+"call");

    }
}

使用lock锁

package com.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * synchronized
 */
public class Demo1 {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(()->{
            phone.sms();
        },"A").start();

        new Thread(()->{
            phone.sms();
        },"B").start();
    }
}

class Phone{

    Lock lock = new ReentrantLock();

    public  void sms(){
        lock.lock();

        try {
            System.out.println(Thread.currentThread().getName()+"sms");
            call();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public   void call(){
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"call");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
}

3、自旋锁

spinlock
在这里插入图片描述
自己写自旋锁

package com.lock;

import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

public class SpinLockDemo {

   AtomicReference<Thread> atomicReference =  new AtomicReference<>();

   //加锁
    public void mylock(){
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName()+"mylock");
        while (!atomicReference.compareAndSet(null,thread)){

        }
    }

    //解锁
    public void  myunlock(){
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName()+"myunlock");
        atomicReference.compareAndSet(thread,null);

    }


}
package com.lock;

import java.util.concurrent.TimeUnit;

public class Test {

    public static void main(String[] args) {
        SpinLockDemo spinLockDemo = new SpinLockDemo();

        new Thread(()->{
            spinLockDemo.mylock();

            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                spinLockDemo.myunlock();
            }

        },"A").start();



        new Thread(()->{
            spinLockDemo.mylock();
            try {
                System.out.println();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                spinLockDemo.myunlock();
            }

        },"B").start();
    }
}

在这里插入图片描述

4、死锁

package com.lock;

import java.util.concurrent.TimeUnit;

public class DeadLockDemo {
    public static void main(String[] args) {
        String lockA="lockA";
        String lockB ="lockB";

        new Thread(new MyThread(lockA,lockB),"T1").start();
        new Thread(new MyThread(lockB,lockA),"T2").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+"==>"+lockB);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lockB){
                System.out.println(Thread.currentThread().getName()+"lock:"+lockB+"==>"+lockA);

            }
        }
    }
}

测试
在这里插入图片描述
1、使用jps定位进程号jps -l

在这里插入图片描述
2、使用jstack 进程号
在这里插入图片描述

相关文章
|
消息中间件 SQL JSON
阿里云物联网平台 “物模型属性” 的分析&&易错点&&上报属性时Payload如何正确组装?
您是否在纠结设备上报了数据,平台到底有没有收到? 您是否很疑惑物模型属性怎么老是不刷新? 您是否不理解物模型属性下发总是不生效? 您是否不知道上报属性时Payload到底该怎么填? 您是否很纳闷物模型属性一会又携带有时间戳,一会又没有? 您是否怀疑能不能自定义物模型属性的时间戳?又如何取到自定义时间戳? 您是否...
8723 3
阿里云物联网平台 “物模型属性” 的分析&&易错点&&上报属性时Payload如何正确组装?
|
Kubernetes Cloud Native 安全
云原生|kubernetes|多集群管理之kubeconfig文件配置和使用(定义,使用方法,合并管理多集群)(一)
云原生|kubernetes|多集群管理之kubeconfig文件配置和使用(定义,使用方法,合并管理多集群)
2311 0
云原生|kubernetes|多集群管理之kubeconfig文件配置和使用(定义,使用方法,合并管理多集群)(一)
|
4月前
|
人工智能 Java 测试技术
SpringBoot 测试实践:单元测试与集成测试
在 Spring Boot 测试中,@MockBean 用于创建完全模拟的 Bean,替代真实对象行为;而 @SpyBean 则用于部分模拟,保留未指定方法的真实实现。两者结合 Mockito 可灵活控制依赖行为,提升测试覆盖率。合理使用 @ContextConfiguration 和避免滥用 @SpringBootTest 可优化测试上下文加载速度,提高测试效率。
258 6
|
9月前
|
存储 SQL 关系型数据库
MySQL 面试题
MySQL 的一些基础面试题
EMQ
|
运维 Linux 网络性能优化
MQTT 5.0 报文解析 05:DISCONNECT
在 MQTT 中,客户端和服务端可以在断开网络连接前向对端发送一个 DISCONNECT 报文,来指示连接关闭的原因。客户端发送的 DISCONNECT 报文还可以影响服务端在连接断开后的行为,例如是否发送遗嘱消息,是否更新会话过期间隔。
EMQ
510 0
MQTT 5.0 报文解析 05:DISCONNECT
|
监控 Dubbo Java
超详细的Sentinel入门
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
超详细的Sentinel入门
|
12月前
|
运维 物联网 Linux
Linux操作系统的演变与未来趋势####
本文通过探讨Linux操作系统的历史沿革、当前主流版本的特点,以及其在服务器、云计算和物联网等新兴领域的应用,旨在揭示Linux在现代计算环境中的重要性。此外,文章还将分析Linux面临的挑战与机遇,预测其未来的发展趋势。希望通过这篇文章,读者能够更好地理解Linux的价值,并对其未来充满期待。 ####
|
Java C++
AIDL与HIDL核心概念
AIDL与HIDL核心概念
415 0
|
人工智能 Java
JVM内存问题之当老年代缓慢增加且Full GC无法清除时,应如何使用MAT进行分析
JVM内存问题之当老年代缓慢增加且Full GC无法清除时,应如何使用MAT进行分析
645 0
|
存储 数据库 索引
B树与B+树的区别
B树与B+树的区别