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客戶端實現。
- package com.framework.code.demo.zook.lock;
-
- import org.apache.curator.RetryPolicy;
- import org.apache.curator.framework.CuratorFramework;
- import org.apache.curator.framework.CuratorFrameworkFactory;
- import org.apache.curator.framework.recipes.locks.InterProcessMutex;
- import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
- import org.apache.curator.retry.ExponentialBackoffRetry;
-
- public class ReadWriteLock {
-
-
- public static void main(String[] args) throws Exception {
- RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
- CuratorFramework client = CuratorFrameworkFactory
- .newClient("192.168.1.103:2181", retryPolicy);
- client.start();
-
- InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, "/read-write-lock");
-
-
- final InterProcessMutex readLock = readWriteLock.readLock();
-
- final InterProcessMutex writeLock = readWriteLock.writeLock();
-
- try {
- readLock.acquire();
- System.out.println(Thread.currentThread() + "獲取到讀鎖");
-
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
-
- writeLock.acquire();
- System.out.println(Thread.currentThread() + "獲取到寫鎖");
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- writeLock.release();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
-
- Thread.sleep(3000);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- readLock.release();
- }
-
- Thread.sleep(1000000);
- client.close();
- }
-
- }
![](http://static.javashuo.com/static/loading.gif)
實現原理:
實現原理與以前介紹的鎖的原理基本相似,這裏主要說明一下不一樣之處。
一、寫入鎖在申請鎖時寫入的節點名稱是這樣的 xxxx-__WRIT__00000000xxx 例如: _c_9b6e456b-94fe-47e7-b968-34027c094b7d-__WRIT__0000000006
二、讀取鎖在申請鎖時寫入的節點名稱是這樣的 xxxx-__READ__00000000xxx 例如: _c_9b6e456b90-9c33-6294665cf525--b6448-__READ__0000000005
區別就是寫入鎖的字符串包含WRIT,讀取所包含READ
獲取鎖的區別:
一、寫入鎖在獲取鎖時的處理與前面文章介紹的原理一直,就是判斷本身前面還有沒有節點,若是沒有就能夠獲取到鎖,若是有就等待前面的節點釋放鎖。
二、讀取鎖在獲取鎖時的處理是,判斷本身前面還有沒有寫入鎖的節點,也就是前面的節點是否包含WRIT,若是有那麼等待前面的節點釋放鎖。
讀取所本身前面有 其它 讀取鎖節點 無所謂,它仍然能夠獲取到鎖,這也就是讀取所能夠多客戶端共享的緣由。