前面我们已经分析过JUC包里面的Lock锁,ReentrantLock锁和semaphore信号量机制。Lock锁实现了比synchronized更灵活的锁机制,Reentrantlock是Lock的实现类,是一种可重入锁,都是每次只有一次线程对资源进行处理;semaphore实现了多个线程同时对一个资源的访问;今天我们要讲的ReadWriteLock锁将实现另外一种很重要的功能:读写分离锁。
假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写,也就是说:读-读能共存,读-写不能共存,写-写不能共存。这就需要一个读/写锁来解决这个问题。
ReadWriteLock简介
我们在JUC包可以看到ReadWriteLock是一个接口,他有一个实现类:ReentrantReadWriteLock,先让我们对读写访问资源的条件做个概述:
- – 读取: 没有线程正在做写操作,且没有线程在请求写操作。
- – 写入: 没有线程正在做读写操作。
如果某个线程想要读取资源,只要没有线程正在对该资源进行写操作且没有线程请求对该资源的写操作即可。同样当有线程想要写资源,但是此刻有线程正在读取资源,那么此刻写资源的操作是不能继续下去的。
我们来看一个例子:
public class ReadWriteLockTest2 { public static void main(String[] args) { final int threadCount = 2; final ExecutorService exService = Executors.newFixedThreadPool(threadCount); final ScoreBoard scoreBoard = new ScoreBoard(); exService.execute(new ScoreUpdateThread(scoreBoard)); exService.execute(new ScoreHealthThread(scoreBoard)); exService.shutdown(); } } class ScoreBoard { private boolean scoreUpdated = false; private int score = 0; String health = "不可用"; final ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock(); public String getMatchHealth() { rrwl.readLock().lock(); if (scoreUpdated) { rrwl.readLock().unlock(); rrwl.writeLock().lock(); try { if (scoreUpdated) { score = fetchScore(); scoreUpdated = false; } rrwl.readLock().lock(); } finally { rrwl.writeLock().unlock(); } } try { if (score % 2 == 0) { health = "Bad Score"; } else { health = "Good Score"; } } finally { rrwl.readLock().unlock(); } return health; } public void updateScore() { try { rrwl.writeLock().lock(); scoreUpdated = true; } finally { rrwl.writeLock().unlock(); } } private int fetchScore() { Calendar calender = Calendar.getInstance(); return calender.get(Calendar.MILLISECOND); } } class ScoreHealthThread implements Runnable { private ScoreBoard scoreBoard; public ScoreHealthThread(ScoreBoard scoreTable) { this.scoreBoard = scoreTable; } @Override public void run() { for(int i= 0; i< 5; i++) { System.out.println("Match Health: "+ scoreBoard.getMatchHealth()); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class ScoreUpdateThread implements Runnable { private ScoreBoard scoreBoard; public ScoreUpdateThread(ScoreBoard scoreTable) { this.scoreBoard = scoreTable; } @Override public void run() { for(int i= 0; i < 5; i++) { System.out.println("Score Updated."); scoreBoard.updateScore(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } <div>本文来源gaodai^.ma#com搞#代!码网</div> }