欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

读写锁分析

时间:2023-07-09

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

JAVA代码演示读写锁(通俗易懂)

前言一、读写锁的基本概念二、代码示例

1.同时调用读锁和写锁2.读锁可以相互兼容 总结


前言

多线程是java的一大核心之一,作为一个java工程师,必须把多线程吃透!


提示:以下是本篇文章正文内容,下面案例可供参考

一、读写锁的基本概念

1)首先读写锁是互斥的,两者不能同时在一个线程的同一个资源内存在(比如一个方法内同时存在读锁和写锁,因为借助对象去调用方法,锁粒度的是对象,加之互斥,所以不能同时存在),不然会发生死锁。

2)一个线程获得了某个资源的读锁,其他线程就不能获得这个资源的写锁(这个资源可以抽象为某个对象好理解一些),但是可以获得读锁,这里的读锁可以抽象为对于读操作来说不加锁。

3)一个线程获得了某个资源的写锁,其他资源就不能获取这个资源的读锁和写锁(防止脏读)

4)举个例子,一个类A,分别有三个方法,B()、C()、D(),其中B()加了写锁,C()加了读锁,D()方法中调用了B()和C()方法,此时必然会发生死锁,因为互斥。

二、代码示例 1.同时调用读锁和写锁

代码如下(示例):

class MyCache{ Map map=new HashMap<>(); ReadWriteLock readWriteLock=new ReentrantReadWriteLock(); public void put(String key,Object V){ try { //加了写锁的方法 readWriteLock.writeLock().lock(); map.put(key, V); }catch (Exception e){ System.out.println(e.getStackTrace()); }finally { readWriteLock.writeLock().unlock(); } } public void get(int key,Object V){ try { readWriteLock.readLock().lock();//加了读锁 System.out.println(Thread.currentThread().getName() + "即将写入"); this.put(String.valueOf(key*3),V);//加了写锁 System.out.println(Thread.currentThread().getName() + "写入完成"); System.out.println(Thread.currentThread().getName()+"即将读"); map.get(key); //加了读锁 System.out.println(Thread.currentThread().getName()+"读完成"); }catch (Exception e){ System.out.println(e.getStackTrace()); }finally { readWriteLock.readLock().unlock(); } }}

main线程:

public class Lock01 { public static void main(String[] args) { MyCache myCache=new MyCache(); for (int i=0;i<5;i++) { int finalI = i; new Thread(() -> { myCache.get(finalI,finalI*3); }).start(); } }}

结果:出现死锁导致阻塞

F:jdk11.06binjava.exe "Thread-0即将写入Thread-1即将写入

2.读锁可以相互兼容

代码如下(示例):

class MyCache{ Map map=new HashMap<>(); ReadWriteLock readWriteLock=new ReentrantReadWriteLock(); public void put(String key,Object V){ try { readWriteLock.readLock().lock(); map.put(key, V); }catch (Exception e){ System.out.println(e.getStackTrace()); }finally { readWriteLock.readLock().lock(); System.out.println(""); } } public void get(int key,Object V){ try { readWriteLock.readLock().lock(); System.out.println(Thread.currentThread().getName() + "即将写入"); this.put(String.valueOf(key*3),V);//加了读锁 System.out.println(Thread.currentThread().getName() + "写入完成"); System.out.println(Thread.currentThread().getName()+"即将读"); map.get(key); //加了读锁 System.out.println(Thread.currentThread().getName()+"读完成"); }catch (Exception e){ System.out.println(e.getStackTrace()); }finally { readWriteLock.readLock().unlock(); } }}

结果:不发生堵塞,多条线程均可获得读锁

Thread-2即将写入Thread-4即将写入Thread-3即将写入Thread-1即将写入Thread-0即将写入Thread-0写入完成Thread-0即将读Thread-0读完成Thread-1写入完成Thread-1即将读Thread-1读完成Thread-3写入完成Thread-3即将读Thread-3读完成Thread-2写入完成Thread-2即将读Thread-2读完成Thread-4写入完成Thread-4即将读Thread-4读完成Process finished with exit code 0


总结

读写锁的概念可以通过mysql辅助理解,当锁的粒度是一张表,如果这张表加了读锁,那所有的线程都可以读,却不能写,当加了写锁,其他线程不能写也不能读,只能等待获得写锁的线程释放锁。

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。