- 一、Java 锁
- 1.1、公平锁和非公平锁
- 1.2、可重入锁(递归锁)原理
- 1.3、自旋锁(spinlock)
- 1.3、读写锁
解释
公平锁解释:多线程情况下,按照申请锁的顺序进行获取锁,先来先得。
非公平锁解释:多线程情况下,获取锁的顺序不是按照申请锁顺序来的。高并发情况下,可能会导致优先级反转或者饥饿现象。
两者区别
公平锁是并发环境下,每个线程获取锁,查看等待队列,如果为空,或线程是等待队列的第一个,则占有锁,否则加入等待队列,按照先进先出规则队列中取到自己。
非公平锁就是上来直接占有锁,尝试失败,在采用公平锁方式。
JAVA 锁
ReentrantLock 属于非公平锁,可以通过构造函数 Booleen值指定,True 公平锁,False 非公平锁。非公平锁优点在于吞吐量比公平锁大
synchronized 也是非公平锁
1.2、可重入锁(递归锁)原理可重入锁 最大作用是避免死锁
package com.xin; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReenterLockDemo { public static void main(String[] args) { Phone phone = new Phone(); System.out.println("================synchronized================"); new Thread(() -> { phone.sendQQ(); }, "t1").start(); new Thread(() -> { phone.sendQQ(); }, "t2").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();} System.out.println("================ReentrantLock================"); Thread t3 = new Thread(phone,"t3"); Thread t4 = new Thread(phone,"t4"); t3.start(); t4.start(); } } class Phone implements Runnable{ public synchronized void sendQQ() { System.out.println(Thread.currentThread().getName() + "t invoke:sendQQ"); sendWeChat(); } public synchronized void sendWeChat() { System.out.println(Thread.currentThread().getName() + "t #####invoke:sendWeChat"); } @Override public void run() { get(); } Lock lock = new ReentrantLock(); public void get() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "t invoke:get"); set(); } finally { lock.unlock(); } } public void set() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "t invoke:set"); } finally { lock.unlock(); } } }1.3、自旋锁(spinlock)
理论
获取线程的锁不会被阻塞,线程会采用循环的方式获取锁,好处减少上下文切换资源浪费,缺点是循环消耗CPU。
代码
package com.xin; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; public class SpinlockDemo { AtomicReference1.3、读写锁
理论
独占锁(写锁):synchronized、ReentrantLock
共享锁(读锁):
互斥锁:ReadWriteLock
代码
读写锁代码
ReentrantReadWriteLock
package com.xin; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockDemo { public static void main(String[] args) { MyCache myCache = new MyCache(); for (int i = 1; i <= 5; i++) { final int ii = i; new Thread(() -> { myCache.set(ii + "", ii + ""); myCache.get(ii + ""); }, String.valueOf(i)).start(); } } } class MyCache { private volatile Mapmap = new HashMap<>(); ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(); public void get(String key) { reentrantReadWriteLock.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + "t 进行读取"); TimeUnit.MILLISECONDS.sleep(300); Object o = map.get(key); System.out.println(Thread.currentThread().getName() + "t 读取值:" + o); } catch (InterruptedException e) { e.printStackTrace(); } finally { reentrantReadWriteLock.readLock().unlock(); } } public void set(String key, Object value) { reentrantReadWriteLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + "t 进行写入" + value.toString()); TimeUnit.MILLISECONDS.sleep(300); map.put(key, value); System.out.println(Thread.currentThread().getName() + "t 写入成功"); } catch (InterruptedException e) { e.printStackTrace(); } finally { reentrantReadWriteLock.writeLock().unlock(); } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)