使用ZooKeeper實現Java跨JVM的分佈式鎖(讀寫鎖)

1、使用ZooKeeper實現Java跨JVM的分佈式鎖java

2、使用ZooKeeper實現Java跨JVM的分佈式鎖(優化構思)apache

3、使用ZooKeeper實現Java跨JVM的分佈式鎖(讀寫鎖)分佈式

 

讀寫鎖:ide

本文在前面倆片的基礎之上介紹如何 使用ZooKeeper實現Java跨JVM的分佈式鎖(讀寫鎖)。性能

 

簡單介紹一下讀寫鎖,在使用讀寫鎖時, 多個客戶端(線程)能夠同時獲取 「讀鎖」, 可是「寫入鎖」是排它的,只能單獨獲取。優化

一、假設A,B線程獲取到 「讀鎖」, 這時C線程就不能獲取 「寫鎖」。ui

二、假設C線程獲取了「寫鎖」,那麼A,B線程就不能獲取「讀鎖」。spa

這在某種狀況下會大幅度提升系統的性能,在單JVM進程內 Java已經提供了這種鎖的機制,能夠參考ReentrantReadWriteLock這個類。.net

 

基於ZK的分佈式讀寫鎖:線程

本文主要介紹ZK的分佈式讀寫鎖,仍是基於Curator客戶端實現。

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. package com.framework.code.demo.zook.lock;  
  2.   
  3. import org.apache.curator.RetryPolicy;  
  4. import org.apache.curator.framework.CuratorFramework;  
  5. import org.apache.curator.framework.CuratorFrameworkFactory;  
  6. import org.apache.curator.framework.recipes.locks.InterProcessMutex;  
  7. import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;  
  8. import org.apache.curator.retry.ExponentialBackoffRetry;  
  9.   
  10. public class ReadWriteLock {  
  11.   
  12.     /** 
  13.      * @param args 
  14.      * @throws Exception  
  15.      */  
  16.     public static void main(String[] args) throws Exception {  
  17.         RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);  
  18.         CuratorFramework client = CuratorFrameworkFactory  
  19.                 .newClient("192.168.1.103:2181", retryPolicy);  
  20.         client.start();  
  21.           
  22.         InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, "/read-write-lock");  
  23.           
  24.         //讀鎖  
  25.         final InterProcessMutex readLock = readWriteLock.readLock();  
  26.         //寫鎖  
  27.         final InterProcessMutex writeLock = readWriteLock.writeLock();  
  28.           
  29.         try {  
  30.             readLock.acquire();  
  31.             System.out.println(Thread.currentThread() + "獲取到讀鎖");  
  32.               
  33.             new Thread(new Runnable() {  
  34.                 @Override  
  35.                 public void run() {  
  36.                     try {  
  37.                         //在讀鎖沒釋放以前不能讀取寫鎖。  
  38.                         writeLock.acquire();  
  39.                         System.out.println(Thread.currentThread() + "獲取到寫鎖");  
  40.                     } catch (Exception e) {  
  41.                         e.printStackTrace();  
  42.                     } finally {  
  43.                         try {  
  44.                             writeLock.release();  
  45.                         } catch (Exception e) {  
  46.                             e.printStackTrace();  
  47.                         }  
  48.                     }  
  49.                 }  
  50.             }).start();  
  51.             //停頓3000毫秒不釋放鎖,這時其它線程能夠獲取讀鎖,卻不能獲取寫鎖。  
  52.             Thread.sleep(3000);  
  53.         } catch (Exception e) {  
  54.             e.printStackTrace();  
  55.         } finally {  
  56.             readLock.release();  
  57.         }  
  58.           
  59.         Thread.sleep(1000000);  
  60.         client.close();  
  61.     }  
  62.   
  63. }  


 

 

實現原理:

實現原理與以前介紹的鎖的原理基本相似,這裏主要說明一下不一樣之處。

一、寫入鎖在申請鎖時寫入的節點名稱是這樣的   xxxx-__WRIT__00000000xxx 例如:   _c_9b6e456b-94fe-47e7-b968-34027c094b7d-__WRIT__0000000006

二、讀取鎖在申請鎖時寫入的節點名稱是這樣的  xxxx-__READ__00000000xxx 例如:    _c_9b6e456b90-9c33-6294665cf525--b6448-__READ__0000000005

區別就是寫入鎖的字符串包含WRIT,讀取所包含READ

 

獲取鎖的區別:

一、寫入鎖在獲取鎖時的處理與前面文章介紹的原理一直,就是判斷本身前面還有沒有節點,若是沒有就能夠獲取到鎖,若是有就等待前面的節點釋放鎖。

二、讀取鎖在獲取鎖時的處理是,判斷本身前面還有沒有寫入鎖的節點,也就是前面的節點是否包含WRIT,若是有那麼等待前面的節點釋放鎖。

讀取所本身前面有 其它 讀取鎖節點 無所謂,它仍然能夠獲取到鎖,這也就是讀取所能夠多客戶端共享的緣由。

相關文章
相關標籤/搜索