18.1、公平锁、非公平锁
公平锁:非常公平,不能够插队,必须先来后到!
非公平锁:非常不公平,可以插队(默认都是非公平锁)
public ReentrantLock() {
sync = new NonfairSync();
}
// 可以通过传递参数true将它变成公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
18.2、可重入锁(递归锁)
Synchtonized
package com.chen.lock;
// Synchronized
public class Demo01 {
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.chen.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo02 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sms();
},"A").start();
new Thread(()->{
phone.sms();
},"B").start();
}
}
class Phone2{
Lock lock = new ReentrantLock();
public void sms(){
lock.lock(); // 细节问题 lock.lock();lock.unlock(); 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();
}
}
}
18.3、自旋锁
spinlock
我们自定义一个锁来测试
package com.chen.lock;
import java.util.concurrent.atomic.AtomicReference;
/**
* 自旋锁
*/
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.chen.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestSpinLock {
public static void main(String[] args) throws InterruptedException {
// Lock lock = new ReentrantLock();
lock.lock();
lock.unlock();
// 底层使用的自旋锁CAS
SpinLockDemo lock = new SpinLockDemo();
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"T1").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"T2").start();
}
}
18.4、死锁
**死锁是什么 **
死锁测试,怎么排除死锁:
package com.chen.lock;
import lombok.SneakyThrows;
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;
}
@SneakyThrows
@Override
public void run() {
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + "lock:" + lockA + "=>get" + lockB);
TimeUnit.SECONDS.sleep(2);
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + "lock:" + lockB + "=>get" + lockA);
}
}
}
}
解决问题
1、使用JPS -l
定位进程号
2、使用jstack 进程号
查看信息
学习视频链接:https://www.bilibili.com/video/BV1B7411L7tE?p=38