【第七章】JUC之读写锁ReetrantReadWriteLock应用

mac2024-03-26  37

一、常见的锁

按世界观来分:

​   乐观锁:Redis数据库;

​   悲观锁:所有关系型数据库都是采用这种方式,如MySQL{分表锁、行锁(行锁并发性更强行锁才会发生死锁)},读写数据时会上锁,只要解锁后才能进行下一步操作。

按功能来分:   分为读锁【共享锁】、写锁【独占锁】,都会发生死锁!应用软件:红蜘蛛、投影仪。

二、代码案例1-1

MyCache资源类

import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; /** * 自定义缓存类(资源类) */ public class MyCache{ private volatile Map<String,String> map =new HashMap<>(); public void put(String key,String value){ try { //存放业务代码 System.out.println( Thread.currentThread().getName()+"\t====准备写入数据"+key); TimeUnit.MILLISECONDS.sleep(300); map.put(key, value); System.out.println( Thread.currentThread().getName()+"\t====成功写入数据"+key); } catch (InterruptedException e) { e.printStackTrace(); } } public void get(String key){ try { System.out.println( Thread.currentThread().getName()+"\t====准备读取数据"+key); TimeUnit.MILLISECONDS.sleep(300); String value= map.get(key); System.out.println( Thread.currentThread().getName()+"\t====成功读取数据"+value); } catch (InterruptedException e) { e.printStackTrace(); } } }

ReadWriteLockDemo线程类

/** * * 线程操作资源类 */ public class ReadWriteLockDemo { public static void main(String[] args) throws InterruptedException { MyCache myCache =new MyCache(); for (int i = 1; i <=5 ; i++) { String key =String.valueOf(i); //5个写线程 new Thread(()->{ myCache.put(key, UUID.randomUUID().toString().substring(0,8)); },key).start(); } TimeUnit.SECONDS.sleep(2); for (int i = 1; i <=5 ; i++) { String key =String.valueOf(i); //5个读线程 new Thread(()->{ myCache.get(key); },key).start(); } } }
打印结果

  可以看出,一条数据还没成功写入,下一条数据就准备写入,完整性被破坏,不符合期望结果!这种情况就是使用到读写锁。

三、代码案例1-2

修改资源类MyCache即可

/** * 自定义缓存类(资源类) */ public class MyCache{ private volatile Map<String,String> map =new HashMap<>(); private ReadWriteLock readWriteLock =new ReentrantReadWriteLock(); public void put(String key,String value){ readWriteLock.writeLock().lock(); //写锁加锁 try { System.out.println( Thread.currentThread().getName()+"\t====准备写入数据"+key); TimeUnit.MILLISECONDS.sleep(300); //睡眠300毫秒 map.put(key, value); System.out.println( Thread.currentThread().getName()+"\t====成功写入数据"+key); } catch (InterruptedException e) { e.printStackTrace(); }finally { readWriteLock.writeLock().unlock();//写锁解锁 } } public void get(String key){ readWriteLock.readLock().lock();//读锁加锁 try { System.out.println( Thread.currentThread().getName()+"\t====准备读取数据"+key); TimeUnit.MILLISECONDS.sleep(300); String value= map.get(key); System.out.println( Thread.currentThread().getName()+"\t====成功读取数据"+value); } catch (InterruptedException e) { e.printStackTrace(); }finally { readWriteLock.readLock().unlock();//读锁加锁 } } }
打印结果

符合期望结果!数据写完之后才会释放资源,读锁可以并发去读,一次性把数据全读出来。

最新回复(0)