Java API除了提供Lock()接口以外,還爲咱們提供了一個讀寫鎖接口ReadWriteLock,使用這個鎖的實現類ReentrantReadWriteLock能夠讓咱們把讀鎖和寫鎖進行分離,對同步數據進行修改的時候使用寫鎖,這時候其餘須要獲取寫鎖的線程會被掛起,同時使用讀鎖的線程也會被掛起。而讀取數據的時候使用讀鎖,這時候使用讀鎖的線程能夠併發訪問,以提升效率。java
public interface ReadWriteLock { /** * Returns the lock used for reading. * * @return the lock used for reading. */ Lock readLock(); /** * Returns the lock used for writing. * * @return the lock used for writing. */ Lock writeLock(); }
咱們模擬一個修改價格的例子,來看一下讀鎖與寫鎖是如何使用的。併發
建立一個價格類,裏面兩個商品的價格以及一個讀寫鎖。在修改價格的方法裏咱們使用寫鎖,在讀取商品價格的方法裏咱們使用讀鎖。修改商品價方法休眠兩秒來模擬修改價格的過程,並打印修改價格信息。dom
public class PriceInfo { private double price1; private double price2; private ReadWriteLock lock; public PriceInfo() { price1 = 1.0; price2 = 2.0; lock = new ReentrantReadWriteLock(); } public double getPrice1() { lock.readLock().lock(); double value = price1; lock.readLock().unlock(); return price1; } public double getPrice2() { lock.readLock().lock(); double value = price2; lock.readLock().unlock(); return price2; } public void setPrice(double price1, double price2) { lock.writeLock().lock(); System.out.printf("Writer: Attemp to modify the price! Price1:%f Price2:%f\n", price1, price2); this.price1 = price1; this.price2 = price2; try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("Writer: Price has been modified: Price1:%f Price2:%f\n", price1, price2); lock.writeLock().unlock(); } }
建立一個價格修改線程,隨機休眠必定時間後修改價格。ide
public class Writer implements Runnable{ private PriceInfo priceInfo; public Writer(PriceInfo priceInfo) { this.priceInfo = priceInfo; } @Override public void run() { double price1 = Math.random() * 10; double price2 = Math.random() * 8; try { Thread.sleep((long) (Math.random() * 10000)); } catch (InterruptedException e) { e.printStackTrace(); } priceInfo.setPrice(price1, price2); } }
建立一個價格讀取線程,每次讀取兩個商品的價格並打印。this
public class Reader implements Runnable { private PriceInfo priceInfo; public Reader(PriceInfo priceInfo) { this.priceInfo = priceInfo; } @Override public void run() { Date date = new Date(); System.out.printf("%s: Price1 %f .%s\n", Thread.currentThread().getName(), priceInfo.getPrice1(), date); System.out.printf("%s: Price2 %f .%s\n", Thread.currentThread().getName(), priceInfo.getPrice2(), date); } }
建立主方法類,啓動三個價格修改線程。而後每一個兩秒啓動一個線程讀取商品價格。線程
public class Main { public static void main(String[] args) { PriceInfo priceInfo = new PriceInfo(); for (int i = 0; i < 3; i++) { Thread threadWriter = new Thread(new Writer(priceInfo)); threadWriter.start(); } while (true) { new Thread(new Reader(priceInfo)).start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
查看控制檯日誌,每次讀取價格都是修改價格以後的新價格,而且在修改價格的2秒內,讀取價格線程處於掛起狀態。日誌
Thread-3: Price1 1.000000 .Fri Nov 25 11:16:35 CST 2016 Thread-3: Price2 2.000000 .Fri Nov 25 11:16:35 CST 2016 Writer: Attemp to modify the price! Price1:9.655775 Price2:4.031177 Writer: Price has been modified: Price1:9.655775 Price2:4.031177 Thread-4: Price1 9.655775 .Fri Nov 25 11:16:37 CST 2016 Thread-4: Price2 4.031177 .Fri Nov 25 11:16:37 CST 2016 Thread-5: Price1 9.655775 .Fri Nov 25 11:16:39 CST 2016 Thread-5: Price2 4.031177 .Fri Nov 25 11:16:39 CST 2016 Writer: Attemp to modify the price! Price1:2.347803 Price2:2.088409 Writer: Price has been modified: Price1:2.347803 Price2:2.088409 Thread-6: Price1 2.347803 .Fri Nov 25 11:16:41 CST 2016 Thread-6: Price2 2.088409 .Fri Nov 25 11:16:41 CST 2016 Thread-7: Price1 2.347803 .Fri Nov 25 11:16:43 CST 2016 Thread-7: Price2 2.088409 .Fri Nov 25 11:16:43 CST 2016 Writer: Attemp to modify the price! Price1:0.981288 Price2:6.281034 Writer: Price has been modified: Price1:0.981288 Price2:6.281034 Thread-8: Price1 0.981288 .Fri Nov 25 11:16:45 CST 2016 Thread-8: Price2 6.281034 .Fri Nov 25 11:16:45 CST 2016 Thread-9: Price1 0.981288 .Fri Nov 25 11:16:47 CST 2016 Thread-9: Price2 6.281034 .Fri Nov 25 11:16:47 CST 2016 Thread-10: Price1 0.981288 .Fri Nov 25 11:16:49 CST 2016 Thread-10: Price2 6.281034 .Fri Nov 25 11:16:49 CST 2016 Thread-11: Price1 0.981288 .Fri Nov 25 11:16:51 CST 2016 Thread-11: Price2 6.281034 .Fri Nov 25 11:16:51 CST 2016