标签:java String ReadWriteLock 读写 util 线程 key import
为什么要使用ReadWriteLock锁呢?
因为它是更加细粒度的操作,可以提升效率
官方文档
1、有两个锁,读锁和写锁
2、可以做到:读可以有多个线程同时操作,写只能有一个线程操作
3、在频繁的读写情况下,适合使用这个读写锁。
4、并且只有一个实现类
5、可以做到:先执行完所有写的线程,再执行读操作。
没有加锁
-
自定义缓存,多个线程进行读,多个线程进行写
-
没有加锁的情况下:
package com.zxh.add; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReadWriteLockDemo { public static void main(String[] args) { MyCache cache = new MyCache(); // 5个写线程 for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(()->{ cache.put(temp + "", temp + ""); }, String.valueOf(i)).start(); } // 5个读线程 for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(()->{ cache.read(temp + ""); }, String.valueOf(i)).start(); } } } /** * 自定义缓存 */ class MyCache{ // volatile,保证原子性,后面会讲 private volatile Map<String, String> map = new HashMap<>(); // 写 public void put(String key, String value){ System.out.println(Thread.currentThread().getName() + "写入" + key); map.put(key, value); System.out.println(Thread.currentThread().getName() + "写入OK"); } // 读 public void read(String key){ System.out.println(Thread.currentThread().getName() + "读取" + map.get(key)); System.out.println(Thread.currentThread().getName() + "读取OK"); } }
存在问题
1、在还没有写完的情况下,就插入了读操作;
2、一个线程没有写完,被另一写线程插队了。
3、还没有写入,读线程就读取了。
加锁
加了Lock锁的情况
package com.zxh.add; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReadWriteLockDemo { public static void main(String[] args) { MyCache2 cache = new MyCache2(); // 5个写线程 for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(()->{ cache.put(temp + "", temp + ""); }, String.valueOf(i)).start(); } // 5个读线程 for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(()->{ cache.read(temp + ""); }, String.valueOf(i)).start(); } } } /** * 自定义缓存 */ class MyCache2{ // volatile,无法保证原子性,后面会讲,但是可以防止指令的重排 private volatile Map<String, String> map = new HashMap<>(); Lock lock = new ReentrantLock(); // 写 public void put(String key, String value){ try { lock.lock(); System.out.println(Thread.currentThread().getName() + "写入" + key); map.put(key, value); System.out.println(Thread.currentThread().getName() + "写入OK"); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } // 读 public void read(String key){ try { lock.lock(); System.out.println(Thread.currentThread().getName() + "读取" + key); map.get(key); System.out.println(Thread.currentThread().getName() + "读取OK"); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
存在问题:
1、没有存放,就进行了读取操作
2、读取的时候,只能有一个线程操作,读完之后,其他线程才能继续,这样效率低,不满足一开始所说的,读可以被多个线程同时操作。
加了ReadWriteLock锁的情况
import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockDemo { public static void main(String[] args) { MyCache3 cache = new MyCache3(); // 5个写线程 for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(()->{ cache.put(temp + "", temp + ""); }, String.valueOf(i)).start(); } // 5个读线程 for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(()->{ cache.read(temp + ""); }, String.valueOf(i)).start(); } } } /** * 自定义缓存,加了ReadWriteLock读写锁 */ class MyCache3{ // volatile,保证原子性,后面会讲 private volatile Map<String, String> map = new HashMap<>(); ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 读写锁 // 写 public void put(String key, String value){ readWriteLock.writeLock().lock(); // 写加锁 try { System.out.println(Thread.currentThread().getName() + "写入" + key); map.put(key, value); System.out.println(Thread.currentThread().getName() + "写入OK"); } catch (Exception e) { e.printStackTrace(); } finally { readWriteLock.writeLock().unlock(); //写解锁 } } // 读 public void read(String key){ readWriteLock.readLock().lock(); // 读加锁 try { System.out.println(Thread.currentThread().getName() + "读取" + map.get(key)); System.out.println(Thread.currentThread().getName() + "读取OK"); } catch (Exception e) { e.printStackTrace(); } finally { readWriteLock.readLock().unlock(); // 读解锁 } } }
可以看到非常完美,先执行完写的线程,再进行读操作;
其次读的操作,是多个线程同时进行的,提高了效率;
标签:java,String,ReadWriteLock,读写,util,线程,key,import
来源: https://www.cnblogs.com/zxhbk/p/12960516.html
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。