Zookeeper分布式锁

以下简单介绍使用Curator来实现zk分布式锁的应用和原理。

1.连接zk的Factory类

 

package com.zk;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class ZkClientFactory {
	 private static CuratorFramework client;
	 //构造全局的zk链接对象
	 public static CuratorFramework  getInstance(String url){
		 if(null == client){
			 synchronized(ZkClientFactory.class){
				 if(null == client){
					 CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder();  
				        client = builder.connectString(url) 
				        		.sessionTimeoutMs(3000)  
				                .connectionTimeoutMs(3000)  
				                .canBeReadOnly(false)  
				                .retryPolicy(new ExponentialBackoffRetry(1000, Integer.MAX_VALUE))  
				                .namespace(null)  
				                .defaultData(null)  
				                .build();  
				        client.start();
				 }
			 }
		 }
		 return client;
	 }
}

2.模拟多个线程来竞争锁

 

 

class MyJob extends Thread{
	CuratorFramework client;
	
	public MyJob(CuratorFramework client){
		this.client = client;
	}
	public void run(){
		InterProcessMutex lock = new InterProcessMutex(client, "/test");
    	try {
			//lock.acquire();//会一直阻塞到获得锁成功
    		boolean locked= lock.acquire(2000, TimeUnit.MILLISECONDS);//获得锁成功或阻塞一定时间返回
    		if(locked){
    			System.out.println(this.getName()+"获取锁成功");
    			Thread.sleep(3000);
    		}else{
    			System.out.println(this.getName()+"获取锁失败");
    		}
		} catch (Exception e) {
	
		}finally{
			try {
				lock.release();
				System.out.println(this.getName()+"释放锁成功");
			} catch (Exception e) {
				
			}
		}
	}
}

 3.测试

public class Lock {
  	private static final String ZK_ADDRESS = "127.0.0.1:2182";
  	
    private static CuratorFramework client = ZkClientFactory.getInstance(ZK_ADDRESS);
    
    public static void main(String[] args){
    	MyJob jb1 = new MyJob(client);
    	MyJob jb2 = new MyJob(client);
    	MyJob jb3 = new MyJob(client);
    	jb1.start();
    	jb2.start();
    	jb3.start();
    }

}

 4.打印结果 :

 

Thread-2获取锁成功

Thread-1获取锁失败

Thread-3获取锁失败

Thread-2释放锁成功

 

 5.假如把加锁的代码换掉:

boolean locked= lock.acquire(2000, TimeUnit.MILLISECONDS);//获得锁成功或阻塞一定时间返回
 if(locked){
    	System.out.println(this.getName()+"获取锁成功");
    	Thread.sleep(3000);
 }else{
    	System.out.println(this.getName()+"获取锁失败");
 }

 换为:

lock.acquire();//会一直阻塞到获得锁成功
System.out.println(this.getName()+"获取锁成功");
Thread.sleep(3000);

 打印结果如下 :

Thread-3获取锁成功

Thread-3释放锁成功

Thread-2获取锁成功

Thread-2释放锁成功

Thread-1获取锁成功

Thread-1释放锁成功

可以看到,3个线程都可以顺序的获得到锁。所以具体使用哪个方法,需要看你的使用场景。

 

猜你喜欢

转载自chenqunhui.iteye.com/blog/2379632