hadoop08---讀寫鎖
阿新 • • 發佈:2018-05-09
The sys 導致 AI while 直接 clas 讀鎖 發生
?ReentrantLock
直接使用lock接口的話,我們需要實現很多方法,不太方便,ReentrantLock是唯一實現了Lock接口的類,並且ReentrantLock提供了更多的方法,ReentrantLock,意思是“可重入鎖”。
以下是ReentrantLock的使用案例:
例子1,lock()的正確使用方法
見代碼MyLockTest
例子2,tryLock()的使用方法
見代碼MyTryLock
例子3,lockInterruptibly()響應中斷的使用方法:
見代碼MyInterruptibly
?ReadWriteLock ReadWriteLock也是一個接口,在它裏面只定義了兩個方法: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(); }
一個用來獲取讀鎖,一個用來獲取寫鎖。也就是說將文件的讀寫操作分開,分成2個鎖來分配給線程,從而使得多個線程可以同時進行讀操作。下面的ReentrantReadWriteLock實現了ReadWriteLock接口。 ?ReentrantReadWriteLock ReentrantReadWriteLock裏面提供了很多豐富的方法,不過最主要的有兩個方法:readLock()和writeLock()用來獲取讀鎖和寫鎖。 下面通過幾個例子來看一下ReentrantReadWriteLock具體用法。 例子1:假如有多個線程要同時進行讀操作的話,先看一下synchronized達到的效果 見代碼MySynchronizedReadWrite 例子2:改成用讀寫鎖的話: 見代碼MyReentrantReadWriteLock
註意: 不過要註意的是,如果有一個線程已經占用了讀鎖,則此時其他線程如果要申請寫鎖,則申請寫鎖的線程會一直等待釋放讀鎖。 如果有一個線程已經占用了寫鎖,則此時其他線程如果申請寫鎖或者讀鎖,則申請的線程會一直等待釋放寫鎖。 ?Lock和synchronized的選擇 1)Lock是一個接口,而synchronized是Java中的關鍵字,synchronized是內置的語言實現; 2)synchronized在發生異常時,會自動釋放線程占有的鎖,因此不會導致死鎖現象發生;而Lock在發生異常時,如果沒有主動通過unLock()去釋放鎖,則很可能造成死鎖現象,因此使用Lock時需要在finally塊中釋放鎖;3)Lock可以讓等待鎖的線程響應中斷,而synchronized卻不行,使用synchronized時,等待的線程會一直等待下去,不能夠響應中斷; 4)通過Lock可以知道有沒有成功獲取鎖,而synchronized卻無法辦到。 5)Lock可以提高多個線程進行讀操作的效率。 在性能上來說,如果競爭資源不激烈,兩者的性能是差不多的,而當競爭資源非常激烈時(即有大量線程同時競爭),此時Lock的性能要遠遠優於synchronized。所以說,在具體使用時要根據適當情況選擇。
package cn.itcast_01_mythread.thread.lock; /** * 一個線程又要讀又要寫,用synchronize來實現的話,讀寫操作都只能鎖住後一個線程一個線程地進行 * @author * */ public class MySynchronizedReadWrite { public static void main(String[] args) { final MySynchronizedReadWrite test = new MySynchronizedReadWrite(); new Thread(){ public void run() { test.get(Thread.currentThread()); }; }.start(); new Thread(){ public void run() { test.get(Thread.currentThread()); }; }.start(); } public synchronized void get(Thread thread) {//get方法被鎖住synchronized,不管是讀還是寫同一時刻只能一個線程進來 long start = System.currentTimeMillis(); int i=0; while(System.currentTimeMillis() - start <= 1) { i++; if(i%4==0){ System.out.println(thread.getName()+"正在進行寫操作"); }else { System.out.println(thread.getName()+"正在進行讀操作"); } } System.out.println(thread.getName()+"讀寫操作完畢"); } }
package cn.itcast_01_mythread.thread.lock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * 使用讀寫鎖,可以實現讀寫分離鎖定,讀操作並發進行,寫操作鎖定單個線程。 * * 讀跟讀不互斥,寫跟寫互斥,讀跟寫互斥 * * 如果有一個線程已經占用了讀鎖,則此時其他線程如果要申請寫鎖,則申請寫鎖的線程會一直等待釋放讀鎖。 * 如果有一個線程已經占用了寫鎖,則此時其他線程如果申請寫鎖或者讀鎖,則申請的線程會一直等待釋放寫鎖。 * @author * */ public class MyReentrantReadWriteLock { private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); public static void main(String[] args) { final MyReentrantReadWriteLock test = new MyReentrantReadWriteLock(); new Thread(){ public void run() {//一邊讀一邊寫 test.get(Thread.currentThread()); test.write(Thread.currentThread()); }; }.start(); new Thread(){ public void run() {//一邊讀一邊寫 test.get(Thread.currentThread()); test.write(Thread.currentThread()); }; }.start(); } /** * 讀操作,用讀鎖來鎖定 * @param thread */ public void get(Thread thread) { rwl.readLock().lock();//讀操作用讀鎖鎖定 try { long start = System.currentTimeMillis(); while(System.currentTimeMillis() - start <= 1) { System.out.println(thread.getName()+"正在進行讀操作"); } System.out.println(thread.getName()+"讀操作完畢"); } finally { rwl.readLock().unlock(); } } /** * 寫操作,用寫鎖來鎖定 * @param thread */ public void write(Thread thread) { rwl.writeLock().lock();//寫操作用寫鎖鎖定 try { long start = System.currentTimeMillis(); while(System.currentTimeMillis() - start <= 1) { System.out.println(thread.getName()+"正在進行寫操作"); } System.out.println(thread.getName()+"寫操作完畢"); } finally { rwl.writeLock().unlock(); } } } //0在讀的時候1可以讀。0在寫的時候別人不可以寫。 /*Thread-0寫操作完畢 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作 Thread-1正在進行寫操作*/
hadoop08---讀寫鎖