各种锁的理解

公平锁,非公平锁

公平锁:不能插队,必须先来后到 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);
            }
        }
    }
}

怎么排除死锁?

  1. 使用 jps -l 定位进程号
  2. 使用 jstack 进程号 查看进程信息

posted @ 2022-01-19 16:11  一刹流云散  阅读(73)  评论(0编辑  收藏  举报