JUC并发编程(基础入门十)——公平锁,非公平锁、可重入锁、自旋锁、死锁

1公平锁,非公平锁

公平锁:非常公平,不能插队,必须先来后到;非公平锁:非常不公平,允许插队,可以改变顺序**(默认)**

public ReentrantLock() {
    
    
    sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
    
    
    sync = fair ? new FairSync() : new NonfairSync();
}

2什么是可重入锁(ReentrantLock)?

ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞

在java关键字synchronized隐式支持重入性,synchronized通过获取自增,释放自减的方式实现重入。与此同时,ReentrantLock还支持公平锁和非公平锁两种方式。那么,要想完完全全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习:1. 重入性的实现原理;2. 公平锁和非公平锁。

3重入性的实现原理

要想支持重入性,就要解决两个问题:1. 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功【同一个线程对象】2.由于锁会被获取n次,那么只有锁在被释放同样的n次之后,该锁才算是完全释放成功。

ReentrantLock支持两种锁:公平锁和非公平锁。何谓公平性,是针对获取锁而言的,如果一个锁是公平的,那么锁的获取顺序就应该符合请求上的绝对时间顺序,满足FIFO。

4Synchonized 锁实现重入

在这里插入图片描述

5Lock 锁实现重入

lock锁必须配对,相当于lock和 unlock 必须数量相同;在外面加的锁,也可以在里面解锁在里面加的锁,在外面也可以解锁

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

//lock
public class Test {
    
    

    public static void main(String[] args) {
    
    
        Phone2 phone = new Phone2();
        new Thread(()->{
    
    
            phone.sms();
        },"A").start();
        new Thread(()->{
    
    
            phone.sms();
        },"B").start();
    }

}
class Phone2{
    
    

    Lock lock=new ReentrantLock();

    public void sms(){
    
    
        lock.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();
        }
    }
}

A=> sms
A=> call
B=> sms
B=> call

6自旋锁

t2进程必须等待t1进程Unlock后,才能Unlock,在这之前进行自旋等待。。。。

public final int getAndAddInt(Object var1, long var2, int var4) {
    
    
    int var5;
    do {
    
    
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
    return var5;
}

7死锁的查看问题

在这里插入图片描述

import java.util.concurrent.TimeUnit;

public class DeadLock {
    
    
    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+"===>get"+lockB);
            try {
    
    
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            synchronized (lockB){
    
    
                System.out.println(Thread.currentThread().getName()+" lock"+lockB+"===>get"+lockA);
            }
        }
    }
}

如何解开死锁
1、使用jps定位进程号,jdk的bin目录下: 有一个jps
命令:jps -l
在这里插入图片描述
使用jstack 进程进程号 找到死锁信息

C:\Users\DELL>jps -l
9380 DeadLock
11016 sun.tools.jps.Jps
10316 org.jetbrains.jps.cmdline.Launcher
19788

C:\Users\DELL>jstack 9380
2021-02-28 16:19:37
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.111-b14 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x00000000034f2800 nid=0x4ca0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"t2" #12 prio=5 os_prio=0 tid=0x000000001e089000 nid=0x3bc waiting for monitor entry [0x000000001ed2f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at MyThread.run(DeadLock.java:33)
        - waiting to lock <0x000000076b49d200> (a java.lang.String)
        - locked <0x000000076b49d238> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)

"t1" #11 prio=5 os_prio=0 tid=0x000000001e084800 nid=0x3484 waiting for monitor entry [0x000000001ec2f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at MyThread.run(DeadLock.java:33)
        - waiting to lock <0x000000076b49d238> (a java.lang.String)
        - locked <0x000000076b49d200> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)

"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x000000001e00f000 nid=0x4100 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001df98000 nid=0x46c8 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001df97000 nid=0x22c8 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x000000001df91000 nid=0x53ec waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001df86000 nid=0x3690 runnable [0x000000001e62e000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:170)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        - locked <0x000000076b5cee00> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        - locked <0x000000076b5cee00> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:47)

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001df38800 nid=0x55d0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001cbef800 nid=0x4354 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001cbca000 nid=0x3c20 in Object.wait() [0x000000001df2e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b308e98> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x000000076b308e98> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001cba9000 nid=0x4b94 in Object.wait() [0x000000001de2f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b306b40> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x000000076b306b40> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=2 tid=0x000000001cba7800 nid=0x39c0 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000003508000 nid=0x2600 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000003509800 nid=0x4be0 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000000000350b000 nid=0x4f60 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000350c800 nid=0x4ea0 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x000000001e082800 nid=0x463c waiting on condition

JNI global references: 16


Found one Java-level deadlock:
=============================
"t2":
  waiting to lock monitor 0x00000000035ece78 (object 0x000000076b49d200, a java.lang.String),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x00000000035ea5e8 (object 0x000000076b49d238, a java.lang.String),
  which is held by "t2"

Java stack information for the threads listed above:
===================================================
"t2":
        at MyThread.run(DeadLock.java:33)
        - waiting to lock <0x000000076b49d200> (a java.lang.String)
        - locked <0x000000076b49d238> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)
"t1":
        at MyThread.run(DeadLock.java:33)
        - waiting to lock <0x000000076b49d238> (a java.lang.String)
        - locked <0x000000076b49d200> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

一般情况信息在最后:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zs18753479279/article/details/114226544