各种锁的理解
公平锁,非公平锁
公平锁:不能插队,必须先来后到 FIFO
非公平锁:可以插队 可以允许短任务优先(默认)
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
可重入锁 递归锁
Synchronized方式
//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(); //包含call方法,只有这两个方法都执行完才能解锁
}
public synchronized void call(){
System.out.println(Thread.currentThread().getName()+" call");
}
}
lock方式
//Lock锁
public class Demo02 {
public static void main(String[] args) {
Phone1 phone = new Phone1();
new Thread(()->{
phone.sms();
},"A").start();
new Thread(()->{
phone.sms();
},"B").start();
}
}
class Phone1{
Lock lock=new ReentrantLock();
public void sms(){
lock.lock(); //两把钥匙,第一把开第一个锁,第二把开第二个方法内的锁
//lock锁必须配对,否则就会死在里面
try{
System.out.println(Thread.currentThread().getName()+" sms");
call(); //包含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();
}
}
}
自旋锁(SpinLock)
/*
* 自旋锁*/
public class SpinLock {
//int 0
//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);
}
}
//测试
public class TestSpinLock {
public static void main(String[] args) throws InterruptedException {
//底层使用自旋锁 CAS实现
SpinLock spinLock=new SpinLock();
new Thread(()->{
spinLock.myLock();
try{
TimeUnit.SECONDS.sleep(3);
}catch (Exception e){
e.printStackTrace();
}finally {
spinLock.myUnlock();
}
},"t1").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
spinLock.myLock();
try{
TimeUnit.SECONDS.sleep(3);
}catch (Exception e){
e.printStackTrace();
}finally {
spinLock.myUnlock();
}
},"t2").start();
}
}
死锁
死锁例子
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);
}
}
}
}
怎么排除死锁?
- 使用
jps -l
定位进程号 - 使用
jstack 进程号
查看进程信息