首页 > 代码库 > JAVA多线程(八)模式-Read Write Lock
JAVA多线程(八)模式-Read Write Lock
Read Write Lock
写入是互斥的,读取是共享的,写入与读取不能同时发生。
适用环境
类似缓存更新的场景。
样例
缓存,多读多写,LRU淘汰。
读写锁
读读共享,读写、写写互斥。
package ReadWriteLock; public class ReadWriteLock { private int waitWriters=0; private int writingWriters=0; private int readers=0; //读写都在等待时,写优先,读线程多,写线程少,防止写线程被饿死 private boolean writeFirst=true; public synchronized void readLock() throws InterruptedException{ while(writingWriters>0||(writeFirst&&waitWriters>0)){ wait(); } readers++; showDetail(Thread.currentThread().getName()+"--"+"readLock"); } public synchronized void readUnlock(){ readers--; writeFirst=true; showDetail(Thread.currentThread().getName()+"--"+"readUnlock"); notifyAll(); } public synchronized void writeLock() throws InterruptedException{ waitWriters++; try{ //读、写过程中不能再写,等待 while(readers>0||writingWriters>0){ wait(); } }finally{ waitWriters--; } writingWriters++; showDetail(Thread.currentThread().getName()+"--"+"writeLock"); } public synchronized void writeUnlock(){ //释放写锁 writingWriters--; //写过,同时等待中的读、写中,读优先。避免连续写,读线程饥饿 writeFirst=false; showDetail(Thread.currentThread().getName()+"--"+"writeUnlock"); notifyAll(); } private void showDetail(String msg){ System.out.println(Thread.currentThread().getName()+"--"+"--------------------------"); System.out.println(Thread.currentThread().getName()+"--"+msg); System.out.println(Thread.currentThread().getName()+"--"+"wait:"+waitWriters); System.out.println(Thread.currentThread().getName()+"--"+"writing:"+writingWriters); System.out.println(Thread.currentThread().getName()+"--"+"read:"+readers); System.out.println(Thread.currentThread().getName()+"--"+"--------------------------"); } }
缓存
基于LinkedHashMap实现
package ReadWriteLock; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; public class SharedBuffer<K,V> { private ReadWriteLock lock=new ReadWriteLock(); private LinkedHashMap<K,V> buf=null; private final int size; public SharedBuffer(final int initsize){ this.size=(int) Math.ceil(initsize / 0.75f) + 1; this.buf=new LinkedHashMap<K,V>(size, 0.75f, true) { private static final long serialVersionUID = -2347727619006196448L; @Override protected boolean removeEldestEntry(Entry<K,V> eldest) { boolean isRemove=size() > initsize; if(isRemove){ System.out.println(Thread.currentThread().getName()+"--"+eldest.getKey()+":"+eldest.getValue()+" 被丢弃!"); } return isRemove; } }; } public void put(K k,V v){ try { lock.writeLock(); System.out.println(Thread.currentThread().getName()+"--"+"buffer after write lock"); System.out.println(Thread.currentThread().getName()+"--"+this.showSnapHost()); } catch (InterruptedException e) { } try{ this.buf.put(k, v); System.out.println(Thread.currentThread().getName()+"--"+"buffer "+k+"->"+v); }finally{ System.out.println(Thread.currentThread().getName()+"--"+this.showSnapHost()); lock.writeUnlock(); System.out.println(Thread.currentThread().getName()+"--"+"buffer after write unlock"); } } public V get(K k){ try { System.out.println(Thread.currentThread().getName()+"--"+"buffer before read lock"); lock.readLock(); System.out.println(Thread.currentThread().getName()+"--"+"buffer after read lock"); } catch (InterruptedException e) { } try { return this.buf.get(k); }finally{ System.out.println(Thread.currentThread().getName()+"--"+this.showSnapHost()); lock.readUnlock(); System.out.println(Thread.currentThread().getName()+"--"+"buffer read unlock"); } } private String showSnapHost() { Map<K,V> copy = new LinkedHashMap<K,V>(this.buf); StringBuilder sb = new StringBuilder(); for (Map.Entry<K,V> entry : copy.entrySet()) { sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue())); } return sb.toString(); } }
读者
package ReadWriteLock; import java.util.Random; public class Reader implements Runnable{ private final SharedBuffer<String,String> buf; private final String myName; public Reader(String myName,SharedBuffer<String,String> buf){ this.myName=myName; this.buf=buf; } @Override public void run() { Random r=new Random(); while(true){ String k=Integer.toString(r.nextInt(10)); System.out.println(Thread.currentThread().getName()+"--"+k+" Readed!!! "+this.myName+":"+buf.get(k)); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } }
写者
package ReadWriteLock; import java.util.Random; public class Writer implements Runnable{ private final SharedBuffer<String,String> buf; private final String myName; public Writer(String myName,SharedBuffer<String,String> buf){ this.myName=myName; this.buf=buf; } @Override public void run() { Random r=new Random(); int cnt=0; while(true){ cnt++; String k=null; if(cnt<=10){ k=Integer.toString(r.nextInt(10)); }else{ k=Integer.toString(r.nextInt(100)); } buf.put(k, ""+cnt); System.out.println(Thread.currentThread().getName()+"--"+k+" writed!! "+this.myName+":"+cnt); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
测试类
package ReadWriteLock; public class Test { public static void main(String[] args) { System.out.println("++++++++++++++++++++++++++++++++++++"); SharedBuffer<String,String> buf=new SharedBuffer<String,String>(10); Reader r1=new Reader("r1",buf); Reader r2=new Reader("r2",buf); Writer w1=new Writer("w1",buf); Writer w2=new Writer("w2",buf); Thread rtd1=new Thread(r1); Thread rtd2=new Thread(r2); Thread wtd1=new Thread(w1); Thread wtd2=new Thread(w2); wtd1.start(); wtd2.start(); try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } rtd1.start(); rtd2.start(); try { rtd1.join(); rtd2.join(); wtd1.join(); wtd2.join(); } catch (InterruptedException e) { e.printStackTrace(); } } }
本文出自 “JAVA技术栈笔记” 博客,请务必保留此出处http://stroll.blog.51cto.com/11038467/1857276
JAVA多线程(八)模式-Read Write Lock
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。