各种锁的理解
一、公平锁、非公平锁
公平锁: 非常公平, 不能够插队,必须先来后到!
非公平锁: 非常不公平,可以插队 (默认都是非公平)
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
二、可重入锁
可重入锁(递归锁)
synchronized
// Synchronized
public class lock {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendSms();
},"A").start();
new Thread(()->{
phone.sendSms();
},"B").start();
}
}
class Phone{
public synchronized void sendSms(){
System.out.println("sendSms");
call(); // 这里也有锁
}
public synchronized void call(){
System.out.println("call");
}
}
Lock
public class lock {
public static void main(String[] args) {
Phone2 phone = new Phone2();
new Thread(()->{
phone.sendSms();
},"A").start();
new Thread(()->{
phone.sendSms();
},"B").start();
}
}
class Phone2{
Lock lock = new ReentrantLock();
public synchronized void sendSms(){
lock.lock(); // 细节问题: lock(); lock.unlock();
// lock 锁必须配对,否则就会死锁
try {
System.out.println("sendSms");
call();// 这里也有锁
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public synchronized void call(){
lock.lock();
try {
System.out.println("call");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
三、自旋锁
spinlock
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
reentrantLock.unlock();
底层使用的自旋锁CAS
/*
* 自旋锁
*/
public class SpinlockDemo {
// int 0
// Thread null
AtomicReference<Thread> atomicReference = new AtomicReference<>();
// 加锁
public void myLock(){
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + "==> mylock");
//
/* if(atomicReference.compareAndSet(null,thread)){
System.out.println(Thread.currentThread().getName() + "wuhu");
}
if(atomicReference.compareAndSet(thread,null)){
System.out.println(Thread.currentThread().getName() + "hahei");
}*/
// 自旋锁
while (!atomicReference.compareAndSet(null,thread)){
// 一开始atomicReference是空的 所以t1吧 atomicReference变为T1的thread就出去了
// thread是null返回true 这里为true是结束循环
// 当T2进来的时候 这时候atomicReference就不为空了 一直循环 等到t1解锁的时候t2才会出去
}
}
// 解锁
public void myUnLock(){
Thread thread = Thread.currentThread(); // 获取运行的线程信息
System.out.println(Thread.currentThread().getName() + "==> myUnlock");
atomicReference.compareAndSet(thread,null);
}
}
测试
public class TestSpinLock {
public static void main(String[] args) throws InterruptedException {
// ReentrantLock reentrantLock = new ReentrantLock();
// reentrantLock.lock();
// reentrantLock.unlock();
// 底层使用的自旋锁CAS
SpinlockDemo lock = new SpinlockDemo();
new Thread(()-> {
lock.myLock();
try {
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"T1").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()-> {
lock.myLock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"T2").start();
}
}
五、死锁
deadLockDemo
死锁测试,怎么排除死锁
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+"=>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 -l
定位进程号
2、使用jstack 进程号
找到死锁问题
排查问题
1、日志
2、堆栈