公平和非公平锁
公平锁 是指多个线程按照申请锁的顺序来获取锁,相似排队打饭,先来后到。
非公平锁 是指多个线程获取锁的顺序并非按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁在高并发的状况下,有可能会形成优先级反转或者饥饿现象web
区别:非公平锁的优势在于吞吐量比公平锁大。缓存
Synchronized、ReentrantLock(默认)是非公平锁,ReentrantLock能够手动设置为公平锁,参数设为true便可。并发
Lock lock=new ReentrantLock(true);
可重入锁 (又称递归锁)
可重入锁(也叫作递归锁)指的是同一线程外层函数得到锁以后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁也便是说,线程能够进入任何一个它已经拥有的锁所同步着的代码块。svg
ReentrantLock、Synchronized就是一个典型的可重入锁函数
可重入锁最大的做用是避免死锁高并发
例如;method01和method02都上了锁,同一个线程 调用 method01时,内存函数method02仍然加锁,他们是同一把锁。
atom
自旋锁
自旋锁是指尝试获取锁的线程不会当即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减小线程上下文切换的消耗,缺点是循环会消耗CPU
手写自旋锁线程
public class DemoTest {
//原子引用线程
AtomicReference atomicReferenc=new AtomicReference<>();
public void mylock(){
Thread thread=Thread.currentThread();
System.out.println(Thread.currentThread().getName()+"\t come in (*^▽^*)");
//进行自旋操做 判断指望的值 为 null , 若是是将thread更新 返回true 结果取反
while (!atomicReferenc.compareAndSet(null,thread)){
}
}
public void myUnLock(){
Thread thread=Thread.currentThread();
// 释然线程, 若是为当前线程,则更新为 null
atomicReferenc.compareAndSet(thread,null);
System.out.println(Thread.currentThread().getName()+"\t invoked myUnLock()");
}
public static void main(String[] args) {
DemoTest demoTest=new DemoTest();
new Thread(()->{
demoTest.mylock();
try {
//睡眠5秒
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
demoTest.myUnLock();
},"aa").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
demoTest.mylock();
demoTest.myUnLock();
},"bb").start();
}
}
共享锁 和 独占锁
独占锁(写锁):指该锁一次只能被一个线程所持有。对ReentrantLock和Synchronized而言都是独占锁3d
共享锁(读锁):指该锁可被多个线程所持有。
对ReentrantReadWriteLock其读锁是共享锁,其写锁是独占锁。
读锁的共享锁可保证并发读是很是高效的,读写,写读,写写的过程是互斥的。code
使用独占共享锁实现建议缓存(基于ReentrantReadWriteLock)
public class MyCache {
private volatile Map map = new HashMap<>();
ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();
public void put(String key, Object value) {
//独占锁(写锁)
rwlock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "\t 正在写入: " + key);
try {
//暂停一会线程
TimeUnit.MILLISECONDS.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "\t 写入完成");
} finally {
rwlock.writeLock().unlock();
}
}
public void get(String key) {
//共享锁(读锁)
rwlock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "\t 正在读取: " + key);
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
Object result = map.get(key);
System.out.println(Thread.currentThread().getName() + "\t 读取完成" + result);
} finally {
rwlock.readLock().unlock();
}
}
public static void main(String[] args) {
MyCache myCache = new MyCache();
for (int i = 0; i <= 5; i++) {
final int tempInt = i;
new Thread(() -> {
myCache.put(tempInt + "", tempInt + "");
}, String.valueOf(i)).start();
}
for (int i = 0; i <= 5; i++) {
final int tempInt = i;
new Thread(() -> {
myCache.get(tempInt + "");
}, String.valueOf(i)).start();
}
}
}