本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
独占锁(写锁)/共享锁(读锁1)/互斥锁
独占锁:指该锁一次只能被-一个线程所持有。对ReentrantLock和Synchronized而言都是独占锁
共享锁:指该锁可被多个线程所持有。
对ReentrantReadWriteLock其读锁是共享锁,其写锁是独占锁。
读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。
读写锁:
例子:登记口的航情,读所有乘客,写只能一个人写
多个线程同时读一个资源类没有任何问题,所以为了“满足并发量,读取共享资源应该可以同时进行。
但是如果有一个线程想去写共享资源来,就不应该再有其它线程可以对该资源进行读或写
读-读能共存
读-写不能共存
写-写不能共有
可读可写绝对业务需求 redis
缓存三大特征:读,写,关闭(清缓存)
kv键值对,重要的是k,不是value,因为k唯一
写操作:洗澡不能洗一半,车队不能被打断(原子性)+独占
必须要加volatile因为保证可见性(航班延误需要第一时间通知)
读写分离 同时贡献
为什么lock能取代sync
sync相当于你上个厕所把学校大门都锁到了 并发性比较差
package com.wsx.readWriteLock;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 读写锁
*/
class Cache{
private volatile Map<String,Object> map = new HashMap<String,Object>();
private ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();
public void put(String key,Object object){
//模块化编程
rwlock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"正在写入......"+key);
try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); }
map.put(key,object);
System.out.println(Thread.currentThread().getName()+"写入完成......");
} catch (Exception e) {
e.printStackTrace();
} finally {
rwlock.writeLock().unlock();
}
}
public void get(String key){
rwlock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"正在读取......");
try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); }
Object result = map.get(key);
System.out.println(Thread.currentThread().getName()+"读取完成......"+result);
} catch (Exception e) {
e.printStackTrace();
} finally {
rwlock.readLock().unlock();
}
}
}
public class ReadWriteLockDemo {
public static void main(String[] args) {
Cache cache = new Cache();
for (int i = 0; i < 5; i++) {
final int tempint = i;
new Thread(()->{
cache.put(tempint+" ",tempint+" ");
},String.valueOf(i)).start();
}
for (int i = 0; i < 5; i++) {
final int tempint = i;
new Thread(()->{
cache.get(tempint+" ");
},String.valueOf(i)).start();
}
}
}