非公平锁和公平锁
非公平锁:非常不公平的锁,效率高!(Lock和synchronized 默认是这个锁)
公平锁:非常公平的锁,遵循先来后到的原则!
非公平锁会直接执行3s
怎么创建呢?
public ReentrantLock() { // 默认非公平锁 sync = new NonfairSync(); } public ReentrantLock(boolean fair) { // 设置为true,就是公平锁 sync = fair ? new FairSync() : new NonfairSync(); }
可重入锁
可重入锁(也叫递归锁)
介绍
代码测试
synchronized版
package com.zxh.lock; public class Demo01 { public static void main(String[] args) { Phone phone = new Phone(); new Thread(()->{ phone.msg(); }, "A").start(); new Thread(()->{ phone.msg(); }, "B").start(); } } class Phone{ public synchronized void msg(){ System.out.println(Thread.currentThread().getName() + " msg()"); call(); } public synchronized void call(){ System.out.println(Thread.currentThread().getName() + "call()"); } }
Lock版
package com.zxh.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Demo02 { public static void main(String[] args) { Phone2 phone = new Phone2(); new Thread(()->{ phone.msg(); }, "A").start(); new Thread(()->{ phone.msg(); }, "B").start(); } } class Phone2{ Lock lock = new ReentrantLock(); // 可重入锁,拿到msg的锁,相对的就拿到了call的锁 public void msg(){ lock.lock(); try { System.out.println(Thread.currentThread().getName() + " msg()"); 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(); } } }
自旋锁
CAS底层就是调用自旋锁
package com.zxh.lock; import org.omg.CORBA.TIMEOUT; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; public class SpinLock { // Thread泛型,内存中的默认值为null private AtomicReference<Thread> atomicReference = new AtomicReference(); // 自定义加锁方法 public void mylock(){ boolean flag; Thread thread = Thread.currentThread(); // 获取调用该锁的线程 System.out.println(thread.getName() + "=> mylock"); // 自旋锁定义,如果我们期望 当前的原子引用的值为null,就修改为当前线程thread /* 线程A和B用的是同一把锁 A进入,atomicReference.compareAndSet(null, thread),因为一开始为null,所以替换内存中值为A线程 替换成功返回true,没有进入循环 B进入,atomicReference.compareAndSet(null, thread),因为已经有了A进程的值 所以替换失败返回false,进入死循环 需要等到A线程解锁,调用atomicReference.compareAndSet(thread, null);方法,将值设置null B线程才可以停止循环,再执行解锁操作 */ while(!atomicReference.compareAndSet(null, thread)){ } } // 自定义解锁方法 public void myunlock(){ Thread thread = Thread.currentThread(); System.out.println(thread.getName() + "=> myunlock"); // 将当前的原子引用的值(内存中的值)修改为null // 因为修改为null之后,mylock方法中的 compareAndSet方法就会修改成功 atomicReference.compareAndSet(thread, null); } }
测试代码
package com.zxh.lock; import java.util.concurrent.TimeUnit; public class TestSpinLock { public static void main(String[] args) throws InterruptedException { SpinLock spinLock = new SpinLock(); new Thread(()->{ spinLock.mylock(); try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } spinLock.myunlock(); },"A").start(); TimeUnit.SECONDS.sleep(1); new Thread(()->{ spinLock.mylock(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } spinLock.myunlock(); },"B").start(); } }
死锁
为什么会发生死锁?
比如:两个线程互相抢夺对方的资源
死锁测试,怎么排除死锁:
package com.zxh.lock; import java.util.concurrent.TimeUnit; public class DeadLockDemo { public static void main(String[] args) { String lockA = "苹果"; String lockB = "蛋糕"; new Thread(new MyThread(lockA, lockB), "A").start(); new Thread(new MyThread(lockB, lockA), "B").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() + "=> " + lockA + " 又想要 " + lockB); synchronized (lockB){ System.out.println(Thread.currentThread().getName() + "=> " + lockB + "又想要 " + lockA); } } } }
因为死锁没有输出,如何排错?
1、使用jps -l
2、使用jstack 进程号
找到死锁问题