1、公平锁、非公平锁
公平锁:非常公平,不能插队,必须先来后到
非公平锁:非常不公平,可以插队(默认都是非公平锁)
Lock lock = new ReentrantLock(); //非公平锁
Lock lock = new ReentrantLock(true); //公平锁
2、可重入锁
递归锁:拿到外面的锁也就拿到里面的锁了
Lock锁必须配对,加了几把锁就要解几把锁!!
3、自旋锁
spinlock
import java.util.concurrent.atomic.AtomicReference;
//自旋锁
public class SpinLockDemo01 {
//Thread null
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);//如果是期望的线程,就置为空
}
}
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/*
测试结果:
t1线程先拿到锁,t2再拿到锁,自旋,等待t1解锁,t2才会解锁
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
// ReentrantLock reentrantLock = new ReentrantLock();
// reentrantLock.lock();
// reentrantLock.unlock();
//底层使用cas实现的自旋锁
SpinLockDemo01 lock = new SpinLockDemo01();
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(2);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"t1").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(2);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"t2").start();
}
}
4、死锁
import java.util.concurrent.TimeUnit;
public class DeadLockDemo {
public static void main(String[] args) {
String lockA = "lockA";
String lockB = "lockB";
MyThread myThread = new MyThread(lockA,lockB);
MyThread myThread1 = new MyThread(lockB,lockA);
new Thread(myThread,"t1").start();
new Thread(myThread1,"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、使用 jsp -l 定位进程号
2、使用 jstack 进程号 找到死锁问题
Synchronized和Lock锁的区别
1.Synchronized是关键字,Lock是java类
2.Synchronized无法判断获取锁的状态,Lock可以判断是否获取锁
3.Synchronized会自动释放锁,Lock手动释放锁
4.Synchronized线程1获得锁,阻塞;线程2等待,Lock锁会trylock()抓取锁
5.Synchronized可重入锁,非公平锁,不可中断的,Lock锁可重入锁,可以中断,公平锁
6.Synchronized锁少量的代码块,Lock锁大量的代码块