1. 程式人生 > >hadoop08---讀寫鎖

hadoop08---讀寫鎖

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---讀寫鎖