ReentrantReadWriteLock & ReentrantLock & Synchronized 區別

1 ReentrantReadWriteLock :(讀寫鎖、寫寫鎖互斥,讀讀鎖共享,經常使用於緩存如terrocotta)緩存

2 ReentrantLock :(可輪詢的、定時的、可中斷 lock() unlock())結合Condition將線程放入相應阻塞隊列,比較靈活  Condition notFull  = lock.newCondition();dom

3 Synchronized (單一對象鎖監視器) 只能單一線程阻塞隊列ide

 

一:可輪詢的、定時的、可中斷的鎖獲取操做性能

(1)可輪詢this

    public void tryLock(){線程

       Lock lock = new ReentrantLock();設計

       if (lock.tryLock()) { //嘗試獲取鎖,若是拿到用鎖,拿不到轉而其它操做orm

       try {對象

       // manipulate protected state索引

       } finally {

       lock.unlock();                                                        

       }

       } else {

       // perform alternative actions

       }

    }

(2)定時鎖

public void tryTimeLock() throws InterruptedException{

       Lock lock = new ReentrantLock();

       if (lock.tryLock(50, TimeUnit.SECONDS)) { //若是線程50秒內未獲取鎖,則超時返回

           try {

              // manipulate protected state

           } finally {

              lock.unlock();

           }

       } else {

           // perform alternative actions

       }

    }

(3)可中斷鎖

 public void lockInterruptibly() throws InterruptedException{

       Lock lock = new ReentrantLock();

        try

            lock.lockInterruptibly(); //優先響應時間中斷,而不是從新獲取鎖

            // manipulate protected state

            lock.unlock(); 

        } 

        catch (InterruptedException e){ 

        } 

    }

 

 

二:公平隊列或非塊結構鎖

public class ReentrantFairLock {

    private volatile long count = 0;// 保持內存可見性,各線程立可見

    private Lock lock;

    public ReentrantFairLock() {

         // 使用非公平鎖,true就是公平鎖

         lock = new ReentrantLock(true);//公平鎖

         //所謂公平鎖就是讓等待最長的線程最先得到該鎖(得到鎖的順序和申請鎖的順序是一致的),性能比非公平鎖性能差

          //lock = new ReentrantLock(false);//非公平鎖(無參數默認)

      }

    public long getValue() {

       return count;

    }

    public void increment() {

       lock.lock(); // 保持操做原子性

       try {

           count++;

       } finally {

           lock.unlock();

       }

    }

}

 

public class ConditionBoundedBuffer{

    final Lock lock = new ReentrantLock();//實例化一個鎖對象 

    final Condition notFull  = lock.newCondition(); //實例化兩個condition(多路等待) 

    final Condition notEmpty = lock.newCondition();  

    final Object[] items = new Object[100];//初始化一個長度爲100的隊列 

    int putptr, takeptr, count; 

    public void put(Object x) throws InterruptedException { 

      lock.lock();//獲取鎖 

      try { 

        while (count == items.length)  //放線程隊列阻塞,喚醒取線程隊列

       notFull.await();//當計數器count等於隊列的長度時,不能在插入,所以等待,線程阻塞在notFull隊列

        items[putptr] = x; //將對象放入putptr索引處 

        if (++putptr == items.length) putptr = 0;//當索引長度等於隊列長度時,將putptr置爲0 緣由是,不能越界插入 

       ++count;//沒放入一個對象就將計數器加1 

        notEmpty.signal();//一旦插入就喚醒取數據線程 

     } finally { 

        lock.unlock();//最後釋放鎖 

     } 

   } 

 

    public Object take() throws InterruptedException{ 

      lock.lock();//獲取鎖 

      try { 

        while (count == 0) //取線程隊列阻塞,喚醒放線程隊列

          notEmpty.await(); 

       Object x = items[takeptr]; //取得takeptr索引處對象 

        if (++takeptr == items.length) takeptr = 0;//當takeptr達到隊列長度時,從零開始取 

       --count;//每取一個講計數器減1 

        notFull.signal();//枚取走一個就喚醒存線程 

        return x; 

     } finally { 

        lock.unlock();//釋放鎖 

     } 

   }  

}

 

 

ReentrantReadWriteLock讀寫鎖:(針對不一樣操做能夠提供不一樣讀或寫鎖 --讀寫鎖、寫寫鎖之間互斥。讀讀鎖共享)

寫鎖和其它任何鎖互斥,讀鎖能夠和其它讀鎖共用,讀寫鎖通常可用於緩存設計

 

1)獲取讀鎖

2)(cachedList == null)釋放讀鎖,獲取寫鎖

3)填充數據

4)釋放寫鎖前獲取讀鎖,而後釋放寫鎖

5)最終是釋放讀鎖

 

 

public class ReadWriteLockTest {

public static void main(String[] args) {

final Queue3 q3 = new Queue3();

for(int i=0;i<3;i++)       

{

new Thread(){

public void run(){

while(true){    //三個線程讀

q3.get();

}

}

}.start();

new Thread(){

public void run(){

while(true){

q3.put(new Random().nextInt(10000)); //三個線程寫

}

}

}.start();

}

}

}

 

class Queue3{

private Object data = null;//共享數據,只能有一個線程能寫該數據,但能夠有多個線程同時讀該數據。

ReadWriteLock rwl = new ReentrantReadWriteLock();//實現接口ReadWriteLock

public void get(){

rwl.readLock().lock(); //兩個線程讀鎖能夠同時進入該讀鎖臨界區內,可是排斥寫鎖

try {

System.out.println(Thread.currentThread().getName() + " be ready to read data!");

Thread.sleep((long)(Math.random()*1000));

System.out.println(Thread.currentThread().getName() + "have read data :" + data);

} catch (InterruptedException e) {

e.printStackTrace();

}finally{

rwl.readLock().unlock();

}

}

public void put(Object data){

 

rwl.writeLock().lock(); //寫鎖排斥其它任何線程鎖進入該寫鎖臨界區

try {

System.out.println(Thread.currentThread().getName() + " be ready to write data!");

Thread.sleep((long)(Math.random()*1000));

this.data = data;

System.out.println(Thread.currentThread().getName() + " have write data: " + data);

} catch (InterruptedException e) {

e.printStackTrace();

}finally{

rwl.writeLock().unlock();

}

}

}

 

ReentrantLock(重入鎖):

public class ReentrantlockTest {

public static void main(String[] args) {

ExecutorService excuteService = Executors.newCachedThreadPool();

final Bussiness bussiness =new Bussiness();

for(int i=0;i<3;i++){

excuteService.submit(new Runnable(){

@Override

public void run() {

bussiness.service();

}

});

}

}

}

 

class Bussiness{

int count =0;

Lock lock = new ReentrantLock();//實現接口Lock

public void service(){

lock.lock();  //上鎖

try{

count++;

System.out.println("count is :"+count);

}catch(Exception e){}

finally{

lock.unlock();//解鎖(出現異常防止死鎖)

}

}

}

相關文章
相關標籤/搜索