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.
一般情况信息在最后: