java锁
1.公平与非公平锁
公平锁:是指多个线程按照申请锁的顺序来获取锁,就是排队,先来后到
非公平锁:是指多个线程获取的顺序并不是按照申请锁的顺序,有可能后申请的线程先获得锁,在高并发的情况下,有可能造成优先级反转或者饥饿现象;
ReentrantLock/Synchronized是默认非公平可重入锁
什么是可重入锁?
指的是同一线程外层函数获得锁之后,内层递归函数仍然能够获取该锁的代码,在同一线程在外层方法获取锁的时候,进入内层方会自动获取锁
1 public synchronized void method1(){ 2 method2(); 3 } 4 public synchronized void method2(){ 5 6 } 7 8 //在同一线程下 9 //可重入锁,就是method1进来了,可以直接调用method2,不管它有没有锁 10 //作用:防止死锁
3.自旋锁
是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗.缺点是循环会消耗cpu;
1 public class LockDemo { 2 AtomicReference<Thread> atomicReference = new AtomicReference<>(); 3 4 public void myLock() { 5 Thread thread = Thread.currentThread(); 6 System.out.println(Thread.currentThread().getName() + " 进来"); 7 while (!atomicReference.compareAndSet(null, thread)) { 8 System.out.println(Thread.currentThread().getName()+" 等待获取"); 9 try { 10 TimeUnit.SECONDS.sleep(1); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 } 15 System.out.println(Thread.currentThread().getName()+" 获取成功"); 16 } 17 public void unLock() { 18 Thread thread=Thread.currentThread(); 19 while (!atomicReference.compareAndSet(thread, null)) { 20 21 } 22 System.out.println(Thread.currentThread().getName()+" 出去"); 23 } 24 25 public static void main(String[] args) { 26 LockDemo lockDemo = new LockDemo(); 27 new Thread(()->{ 28 lockDemo.myLock(); 29 try { 30 TimeUnit.SECONDS.sleep(5); 31 } catch (InterruptedException e) { 32 e.printStackTrace(); 33 } 34 lockDemo.unLock(); 35 },"a").start(); 36 37 new Thread(()->{ 38 lockDemo.myLock(); 39 lockDemo.unLock(); 40 },"b").start(); 41 } 42 } 43
运行结果:
a 进来
b 进来
b 等待获取
a 获取成功
b 等待获取
b 等待获取
b 等待获取
b 等待获取
a 出去
b 获取成功
b 出去
从结果可以看出:a线程运行结束,b线程才开始执行,但是b线程并未停止运行,而是不断的尝试获取线程,知道a线程结束,这就是自旋锁;
4.独占锁(写锁)/共享锁(读锁)/互斥锁
实例:
1 class MyCache{//资源类 2 3 Map<String,Object> map=new HashMap<>(); 4 private ReentrantReadWriteLock reLock=new ReentrantReadWriteLock(); 5 6 7 public void put(String key, Object value) { 8 9 reLock.writeLock().lock(); 10 try{ 11 System.out.println(Thread.currentThread().getName()+" 正在写入"); 12 try { 13 TimeUnit.MILLISECONDS.sleep(500); 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } 17 map.put(key,value); 18 System.out.println(Thread.currentThread().getName()+" 写入完成"); 19 }catch (Exception e){ 20 e.printStackTrace(); 21 }finally { 22 reLock.writeLock().unlock(); 23 } 24 } 25 26 public void get() { 27 28 reLock.readLock().lock(); 29 try{ 30 System.out.println(Thread.currentThread().getName()+" 正在读取"); 31 try { 32 TimeUnit.MILLISECONDS.sleep(500); 33 } catch (InterruptedException e) { 34 e.printStackTrace(); 35 } 36 System.out.println(Thread.currentThread().getName()+" 读取完成"); 37 38 }catch (Exception e){ 39 e.printStackTrace(); 40 }finally { 41 reLock.readLock().unlock(); 42 } 43 } 44 45 } 46 public class ReadWriteLockDemo { 47 48 49 public static void main(String[] args) { 50 MyCache myCache = new MyCache(); 51 for (int i = 0; i <5 ; i++) { 52 new Thread(()->{ 53 myCache.put(Thread.currentThread().getName(),Thread.currentThread().getName()); 54 },String.valueOf(i)).start(); 55 } 56 try { 57 TimeUnit.SECONDS.sleep(5); 58 } catch (InterruptedException e) { 59 e.printStackTrace(); 60 } 61 for (int i = 0; i <5 ; i++) { 62 new Thread(()->{ 63 myCache.get(); 64 },String.valueOf(i)).start(); 65 } 66 } 67 }