java 共享锁 独占锁_java锁—公平/非公平锁、可重入锁、自旋锁、共享/独占锁

公平和非公平锁

公平锁 是指多个线程按照申请锁的顺序来获取锁,相似排队打饭,先来后到。

非公平锁 是指多个线程获取锁的顺序并非按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁在高并发的状况下,有可能会形成优先级反转或者饥饿现象web

区别:非公平锁的优势在于吞吐量比公平锁大。缓存

Synchronized、ReentrantLock(默认)是非公平锁,ReentrantLock能够手动设置为公平锁,参数设为true便可。并发

Lock lock=new ReentrantLock(true);

可重入锁 (又称递归锁)

可重入锁(也叫作递归锁)指的是同一线程外层函数得到锁以后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁也便是说,线程能够进入任何一个它已经拥有的锁所同步着的代码块。svg

ReentrantLock、Synchronized就是一个典型的可重入锁函数

可重入锁最大的做用是避免死锁高并发

例如;method01和method02都上了锁,同一个线程 调用 method01时,内存函数method02仍然加锁,他们是同一把锁。

3c6ce88d2dd67eda79f1c90abb179757.pngatom

自旋锁

自旋锁是指尝试获取锁的线程不会当即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减小线程上下文切换的消耗,缺点是循环会消耗CPU

2f5909e81bc178150a1ce920fe07b55d.png

手写自旋锁线程

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();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值