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 进程号
在这里插入图片描述

相关文章
|
1月前
|
缓存 Java
java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
本文介绍了几种常见的锁机制,包括公平锁与非公平锁、可重入锁与不可重入锁、自旋锁以及读写锁和互斥锁。公平锁按申请顺序分配锁,而非公平锁允许插队。可重入锁允许线程多次获取同一锁,避免死锁。自旋锁通过循环尝试获取锁,减少上下文切换开销。读写锁区分读锁和写锁,提高并发性能。文章还提供了相关代码示例,帮助理解这些锁的实现和使用场景。
java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
|
7月前
|
安全 Java 测试技术
Java并发编程:理解线程同步和锁
【5月更文挑战第25天】本文深入探讨了Java并发编程的核心概念,即线程同步和锁。通过详细解释这两种机制,我们能够理解它们如何帮助解决多线程环境中的竞态条件问题。此外,文章还提供了一些示例代码,以展示如何在Java中使用这些技术。
|
2月前
|
Java API
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
43 0
|
3月前
|
安全 Java
JUC锁: ReentrantReadWriteLock详解
`ReentrantReadWriteLock` 主要用于实现高性能的并发读取,而在写操作相对较少的场景中表现尤为突出。它保证了数据的一致性和线程安全,在合适的场合合理使用 `ReentrantReadWriteLock`,可以实现更加细粒度的控制,并显著提升应用性能。然而,需要注意它的复杂度较一般的互斥锁高,因此在选择使用时要仔细考虑其适用场景。
41 1
|
Linux API C++
锁、避免死锁等相关
锁、避免死锁等相关
71 0
理论:第十章:公平锁,非公平锁,可重入锁,递归锁,自旋锁,读写锁,悲观锁,乐观锁,行锁,表锁,死锁,分布式锁,线程同步锁分别是什么?
理论:第十章:公平锁,非公平锁,可重入锁,递归锁,自旋锁,读写锁,悲观锁,乐观锁,行锁,表锁,死锁,分布式锁,线程同步锁分别是什么?
107 0
|
缓存 Oracle 关系型数据库
可重入读写锁ReentrantReadWriteLock的使用详解
ReentrantReadWriteLock是一把可重入读写锁,这篇文章主要是从使用的角度帮你理解,希望对你有帮助。
226 0
可重入读写锁ReentrantReadWriteLock的使用详解
|
安全 调度
可重入锁
JUC学习
133 0
|
缓存
ReadWriteLock可重入读写锁读写锁
ReadWriteLock可重入读写锁读写锁
170 0
Java 独占锁与共享锁、公平锁与非公平锁、可重入锁
Java 独占锁与共享锁、公平锁与非公平锁、可重入锁