锁所提供的最重要的改进之一就是ReadWriteLock接口和唯一 一个实现它的ReentrantReadWriteLock类。这个类提供两把锁,一把用于读操作和一把用于写操作。同时可以有多个线程执行读操作,但只有一个线程可以执行写操作。当一个线程正在执行一个写操作,不可能有任何线程执行读操作。
参考http://ifeve.com/basic-thread-synchronization-6/#more-7030 做了优化的例子
创建了5个读线程、一个写线程,分别读10次、写3次
PricesInfo
package threadTest.reentrantReadWriteLockTest; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class PricesInfo { private double price1; private double price2; private ReadWriteLock lock; public PricesInfo() { this.price1 = 1.0; this.price2 = 2.0; this.lock = new ReentrantReadWriteLock(); } public double getPrice1() { lock.readLock().lock(); System.out.printf("%s : Price1 开始读了! " ,Thread.currentThread().getName()); double value = price1; System.out.printf("%s : Price1 读取完毕 : %f " ,Thread.currentThread().getName(),value); lock.readLock().unlock(); return value; } public double getPrice2() { lock.readLock().lock(); System.out.printf("%s : Price2开始读了! " ,Thread.currentThread().getName()); double value = price2; System.out.printf("%s : Price2读取完毕 : %f " ,Thread.currentThread().getName(),value); lock.readLock().unlock(); return value; } public void setPrices(double price1, double price2) { lock.writeLock().lock(); System.out.printf("Writer:Attempt to modify the price. "); this.price2 = price2; this.price1 = price1; System.out.printf("Writer:Prices have been modified. "); lock.writeLock().unlock(); } }
Reader
package threadTest.reentrantReadWriteLockTest; public class Reader implements Runnable { private PricesInfo priceInfo; public Reader(PricesInfo priceInfo) { this.priceInfo = priceInfo; } @Override public void run() { for (int i = 0; i < 10; i++) { priceInfo.getPrice1(); priceInfo.getPrice2(); try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Writer
package threadTest.reentrantReadWriteLockTest; public class Writer implements Runnable { private PricesInfo pricesInfo; public Writer(PricesInfo pricesInfo) { this.pricesInfo = pricesInfo; } @Override public void run() { for (int i = 0; i < 3; i++) { pricesInfo.setPrices((i+1)* 10, (i+1) * 100); try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } }
main函数
package threadTest.reentrantReadWriteLockTest; public class App1 { public static void main(String[] args) { PricesInfo pricesInfo = new PricesInfo(); Reader[] readers = new Reader[5]; Thread[] threadsReader = new Thread[5]; for (int i = 0; i < 5; i++) { readers[i] = new Reader(pricesInfo); threadsReader[i] = new Thread(readers[i]); } Writer writer = new Writer(pricesInfo); Thread threadWriter = new Thread(writer); for (int i = 0; i < 5; i++) { threadsReader[i].start(); } threadWriter.start(); } }
结果如下
使用ReentrantReadWriteLock,同时可以有多个线程执行读操作,但只有一个线程可以执行写操作