zk实现分布式锁

1。pom引入依赖

<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>2.11.1</version>
</dependency>

2.demo

CuratorDemo.java

package com.ujia.wb.zk.curator;


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.retry.ExponentialBackoffRetry;


public class CuratorDemo {
public static void main(String[] args) throws Exception {  
        for (int i = 0; i < 10; i++) {  
            //启动10个线程模拟多个客户端  
            Jvmlock jl = new Jvmlock(i);  
            new Thread(jl).start();  
            //这里加上300毫秒是为了让线程按顺序启动,不然有可能4号线程比3号线程先启动了,这样测试就不准了。  
            Thread.sleep(300);  
        }  
    }  
      
    public static class Jvmlock implements Runnable{  
          
        private int num;  
        public Jvmlock(int num) {  
            this.num = num;  
        }  
          
        @Override  
        public void run() {  
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);  
            CuratorFramework client = CuratorFrameworkFactory  
                    .newClient("127.0.0.1:2181", retryPolicy);  
            client.start();  
              
            InterProcessMutex lock = new InterProcessMutex(client,  
                    "/mylock");  
            try {  
                System.out.println("我是第" + num + "号线程,我开始获取锁");  
                lock.acquire();  
                System.out.println("我是第" + num + "号线程,我已经获取锁");  
                Thread.sleep(10000);  
            } catch (Exception e) {  
                e.printStackTrace();  
            } finally {  
                try {  
                    lock.release();  
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
            }  
            client.close();  
        }  
    }  
}


DistributedLock.java


package com.ujia.wb.zk.curator;


import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;


import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;


public class DistributedLock {
// 我们用一个static的map模拟一个第三方独立缓存
public static Map<String, Object> redis = new HashMap<String, Object>();
public static final String key = "redisKey";


public static void main(String[] args) throws InterruptedException {
// 创建俩个对象分别模拟2个进程
RedisProcess processA = new RedisProcess();
RedisProcess processB = new RedisProcess();


// 每个进程别分用50个线程并发请求
ExecutorService service = Executors.newFixedThreadPool(100);
for (int i = 0; i < 50; i++) {
service.execute(processA);
service.execute(processB);
}


service.shutdown();
service.awaitTermination(30, TimeUnit.SECONDS);
}


public static class RedisProcess implements Runnable {
CuratorFramework client;
// ZK分布式锁
InterProcessMutex distributedLock;
// JVM内部锁
ReentrantLock jvmLock;


public RedisProcess() {
client = CuratorFrameworkFactory.newClient("localhost:2181", new ExponentialBackoffRetry(1000, 3));
client.start();
// distributedLock = new InterProcessMutex(client, "/mylock", new
// NoFairLockDriver());
distributedLock = new InterProcessMutex(client, "/mylock");
jvmLock = new ReentrantLock();
}


@Override
public void run() {
// (1)首先判断缓存内资源是否存在
if (redis.get(key) == null) {
try {


// 这里延时1000毫秒的目的是防止线程过快的更新资源,那么其它线程在步骤(1)处就返回true了.
Thread.sleep(1000);


// 获取JVM锁(同一进程内有效)
jvmLock.lock();


// (2)再次判断资源是否已经存在
if (redis.get(key) == null) {
System.out.println("线程:" + Thread.currentThread() + "获取到JVM锁,redis.get(key)为空, 准备获取ZK锁");


// 这里延时500毫秒的目的是防止线程过快更新资源,其它线程在步骤(2)就返回true了。
Thread.sleep(500);
try {
// 获取zk分布式锁
distributedLock.acquire();
System.out.println("线程:" + Thread.currentThread() + "获取到JVM锁,redis.get(key)为空, 获取到了ZK锁");


// 再次判断,如果为空这时可以更新资源
if (redis.get(key) == null) {
redis.put(key, Thread.currentThread() + "更新了缓存");
System.out.println("线程:" + Thread.currentThread() + "更新了缓存");
} else {
System.out.println("线程:" + Thread.currentThread() + "当前资源已经存在,不需要更新");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放ZK锁
try {
distributedLock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
System.out.println(
"线程:" + Thread.currentThread() + "获取到JVM锁,redis.get(key)不为空," + redis.get(key));
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 释放JVM锁
jvmLock.unlock();
}
} else {
System.out.println(redis.get(key));
}
}
}
}



DistributedReentrantReadWriteLock.java


package com.ujia.wb.zk.curator;


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 DistributedReentrantReadWriteLock {
public static void main(String[] args) throws Exception {  
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);  
        CuratorFramework client = CuratorFrameworkFactory  
                .newClient("localhost: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();  
            //停顿3000毫秒不释放锁,这时其它线程可以获取读锁,却不能获取写锁。  
            Thread.sleep(3000);  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            readLock.release();  
        }  
          
        Thread.sleep(1000000);  
        client.close();  
    }  
}


自己实现

DistributedLock.java

package com.ujia.wb.zk.lock;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;


import org.apache.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;


public class DistributedLock implements Lock, Watcher {
private ZooKeeper zk;


private String root = "/locks";


private String lockName;


private String waitNode;


private String myZnode;


private CountDownLatch latch;


private int sessionTimeout = 30000;


private List<Exception> exception = new ArrayList<Exception>();


private static Logger log = Logger.getLogger(DistributedLock.class);


public DistributedLock(String config, String lockName) {


this.lockName = lockName;


try {


zk = new ZooKeeper(config, sessionTimeout, this);


Stat stat = zk.exists(root, false);


if (stat == null) {


zk.create(root, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);


}


} catch (IOException e) {


e.printStackTrace();


exception.add(e);


} catch (KeeperException e) {


e.printStackTrace();


exception.add(e);


} catch (InterruptedException e) {


e.printStackTrace();


exception.add(e);


}


}


public void process(WatchedEvent event) {


if (this.latch != null) {


this.latch.countDown();


}


}


public void lock() {


if (exception.size() > 0) {


throw new LockException(exception.get(0));


}


try {


if (this.tryLock()) {


System.out.println("Thread " + Thread.currentThread().getId() + " " + myZnode + " get lock true");


return;


} else {


waitForLock(waitNode, sessionTimeout);


}


} catch (KeeperException e) {


e.printStackTrace();


throw new LockException(e);


} catch (InterruptedException e) {


e.printStackTrace();


throw new LockException(e);


}


}


public boolean tryLock() {


try {


String splitStr = "_lock_";


if (lockName.contains(splitStr))


throw new LockException("lockName can not contains \\u000B");


myZnode = zk.create(root + "/" + lockName + splitStr, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);


System.out.println(myZnode + " is created ");


List<String> subNodes = zk.getChildren(root, false);


List<String> lockObjNodes = new ArrayList<String>();


for (String node : subNodes) {


String _node = node.split(splitStr)[0];


if (_node.equals(lockName)) {


lockObjNodes.add(node);


}


}


Collections.sort(lockObjNodes);


System.out.println(myZnode + "==" + lockObjNodes.get(0));


if (myZnode.equals(root + "/" + lockObjNodes.get(0))) {


return true;


}


String subMyZnode = myZnode.substring(myZnode.lastIndexOf("/") + 1);


waitNode = lockObjNodes.get(Collections.binarySearch(lockObjNodes, subMyZnode) - 1);


} catch (KeeperException e) {


e.printStackTrace();


throw new LockException(e);


} catch (InterruptedException e) {


e.printStackTrace();


throw new LockException(e);


}


return false;


}


public boolean tryLock(long time, TimeUnit unit) {


try {


if (this.tryLock()) {


return true;


}


return waitForLock(waitNode, time);


} catch (Exception e) {


e.printStackTrace();


}


return false;


}


private boolean waitForLock(String lower, long waitTime)


throws InterruptedException, KeeperException {


Stat stat = zk.exists(root + "/" + lower, true);


if (stat != null) {


System.out.println("Thread " + Thread.currentThread().getId() + " waiting for " + root + "/" + lower);


this.latch = new CountDownLatch(1);


this.latch.await(waitTime, TimeUnit.MILLISECONDS);


this.latch = null;


}


return true;


}


public void unlock() {


try {


System.out.println("unlock " + myZnode);


zk.delete(myZnode, -1);


myZnode = null;


zk.close();


} catch (InterruptedException e) {


e.printStackTrace();


} catch (KeeperException e) {


e.printStackTrace();


}


}


public void lockInterruptibly() throws InterruptedException {


this.lock();


}


public Condition newCondition() {


return null;


}


public class LockException extends RuntimeException {


private static final long serialVersionUID = 1L;


public LockException(String e) {


super(e);


}


public LockException(Exception e) {


super(e);


}


}


}


DistributedReentrantReadWriteLock.java


package com.ujia.wb.zk.lock;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;


public class DistributedReentrantReadWriteLock implements ReadWriteLock, Watcher{
private  static String lockName;
private static DistributedReentrantReadWriteLock.WriteLock writerLock;
private static ZooKeeper zk;
private static final int sessionTimeout = 30000;
private static String root = "/locks";
private static CountDownLatch latch;


 /**
     * Creates a new {@code ReentrantReadWriteLock} with
     * the given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
* @throws Exception 
     */
    public DistributedReentrantReadWriteLock(boolean fair,String config,String lockName) throws Exception {
//        sync = fair ? new FairSync() : new NonfairSync();
//        readerLock = new ReadLock(this);
    this.lockName = lockName;
        writerLock = new WriteLock(this);
        zk= new ZooKeeper(config, sessionTimeout, this);
        
        Stat stat = zk.exists(root, false);


if (stat == null) {


zk.create(root, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);


}
    }

  /**
     * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
     */
    public static class WriteLock implements Lock  {
//        private final Sync sync;
        private final String lockName;
        private String waitNode;


    private  String myZnode;


//     private int sessionTimeout = 30000;
   
//     private ZooKeeper zk;


//     private String root = "/locks";
//     private CountDownLatch latch;


        /**
         * Constructor for use by subclasses
         *
         * @param lock the outer lock object
         * @throws NullPointerException if the lock is null
         */
        protected WriteLock(DistributedReentrantReadWriteLock lock) {
//            sync = lock.sync;
            lockName = lock.lockName;
          
        }


        /**
         * Acquires the write lock.
         *
         * <p>Acquires the write lock if neither the read nor write lock
         * are held by another thread
         * and returns immediately, setting the write lock hold count to
         * one.
         *
         * <p>If the current thread already holds the write lock then the
         * hold count is incremented by one and the method returns
         * immediately.
         *
         * <p>If the lock is held by another thread then the current
         * thread becomes disabled for thread scheduling purposes and
         * lies dormant until the write lock has been acquired, at which
         * time the write lock hold count is set to one.
         */
        public void lock() {
//            sync.acquire(1);
        try {


    if (this.tryLock()) {


    System.out.println("Thread " + Thread.currentThread().getId() + " " + myZnode + " get lock true");


    return;


    } else {


    waitForLock(waitNode, sessionTimeout);


    }


    } catch (KeeperException e) {


    e.printStackTrace();


//     throw new LockException(e);


    } catch (InterruptedException e) {


    e.printStackTrace();


//     throw new LockException(e);


    }
        }
 


        /**
         * Acquires the write lock unless the current thread is
         * {@linkplain Thread#interrupt interrupted}.
         *
         * <p>Acquires the write lock if neither the read nor write lock
         * are held by another thread
         * and returns immediately, setting the write lock hold count to
         * one.
         *
         * <p>If the current thread already holds this lock then the
         * hold count is incremented by one and the method returns
         * immediately.
         *
         * <p>If the lock is held by another thread then the current
         * thread becomes disabled for thread scheduling purposes and
         * lies dormant until one of two things happens:
         *
         * <ul>
         *
         * <li>The write lock is acquired by the current thread; or
         *
         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
         * the current thread.
         *
         * </ul>
         *
         * <p>If the write lock is acquired by the current thread then the
         * lock hold count is set to one.
         *
         * <p>If the current thread:
         *
         * <ul>
         *
         * <li>has its interrupted status set on entry to this method;
         * or
         *
         * <li>is {@linkplain Thread#interrupt interrupted} while
         * acquiring the write lock,
         *
         * </ul>
         *
         * then {@link InterruptedException} is thrown and the current
         * thread's interrupted status is cleared.
         *
         * <p>In this implementation, as this method is an explicit
         * interruption point, preference is given to responding to
         * the interrupt over normal or reentrant acquisition of the
         * lock.
         *
         * @throws InterruptedException if the current thread is interrupted
         */
        public void lockInterruptibly() throws InterruptedException {
//            sync.acquireInterruptibly(1);
        }


        /**
         * Acquires the write lock only if it is not held by another thread
         * at the time of invocation.
         *
         * <p>Acquires the write lock if neither the read nor write lock
         * are held by another thread
         * and returns immediately with the value {@code true},
         * setting the write lock hold count to one. Even when this lock has
         * been set to use a fair ordering policy, a call to
         * {@code tryLock()} <em>will</em> immediately acquire the
         * lock if it is available, whether or not other threads are
         * currently waiting for the write lock.  This &quot;barging&quot;
         * behavior can be useful in certain circumstances, even
         * though it breaks fairness. If you want to honor the
         * fairness setting for this lock, then use {@link
         * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
         * which is almost equivalent (it also detects interruption).
         *
         * <p>If the current thread already holds this lock then the
         * hold count is incremented by one and the method returns
         * {@code true}.
         *
         * <p>If the lock is held by another thread then this method
         * will return immediately with the value {@code false}.
         *
         * @return {@code true} if the lock was free and was acquired
         * by the current thread, or the write lock was already held
         * by the current thread; and {@code false} otherwise.
         */
        public boolean tryLock( ) {
//            return sync.tryWriteLock();
        try {


    String splitStr = "_lock_";


    if (lockName.contains(splitStr)){


//     throw new LockException("lockName can not contains \\u000B");
    throw new Exception("lockName can not contains \\u000B");
    }
    myZnode = zk.create(root + "/" + lockName + splitStr, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE,
    CreateMode.EPHEMERAL_SEQUENTIAL);


    System.out.println(myZnode + " is created ");


    List<String> subNodes = zk.getChildren(root, false);


    List<String> lockObjNodes = new ArrayList<String>();


    for (String node : subNodes) {


    String _node = node.split(splitStr)[0];


    if (_node.equals(lockName)) {


    lockObjNodes.add(node);


    }


    }


    Collections.sort(lockObjNodes);


    System.out.println(myZnode + "==" + lockObjNodes.get(0));


    if (myZnode.equals(root + "/" + lockObjNodes.get(0))) {


    return true;


    }


    String subMyZnode = myZnode.substring(myZnode.lastIndexOf("/") + 1);


    waitNode = lockObjNodes.get(Collections.binarySearch(lockObjNodes, subMyZnode) - 1);


    } catch (KeeperException e) {


    e.printStackTrace();


//     throw new LockException(e);


    } catch (InterruptedException e) {


    e.printStackTrace();


//     throw new LockException(e);


    } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


    return false;
        }


        /**
         * Acquires the write lock if it is not held by another thread
         * within the given waiting time and the current thread has
         * not been {@linkplain Thread#interrupt interrupted}.
         *
         * <p>Acquires the write lock if neither the read nor write lock
         * are held by another thread
         * and returns immediately with the value {@code true},
         * setting the write lock hold count to one. If this lock has been
         * set to use a fair ordering policy then an available lock
         * <em>will not</em> be acquired if any other threads are
         * waiting for the write lock. This is in contrast to the {@link
         * #tryLock()} method. If you want a timed {@code tryLock}
         * that does permit barging on a fair lock then combine the
         * timed and un-timed forms together:
         *
         *  <pre> {@code
         * if (lock.tryLock() ||
         *     lock.tryLock(timeout, unit)) {
         *   ...
         * }}</pre>
         *
         * <p>If the current thread already holds this lock then the
         * hold count is incremented by one and the method returns
         * {@code true}.
         *
         * <p>If the lock is held by another thread then the current
         * thread becomes disabled for thread scheduling purposes and
         * lies dormant until one of three things happens:
         *
         * <ul>
         *
         * <li>The write lock is acquired by the current thread; or
         *
         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
         * the current thread; or
         *
         * <li>The specified waiting time elapses
         *
         * </ul>
         *
         * <p>If the write lock is acquired then the value {@code true} is
         * returned and the write lock hold count is set to one.
         *
         * <p>If the current thread:
         *
         * <ul>
         *
         * <li>has its interrupted status set on entry to this method;
         * or
         *
         * <li>is {@linkplain Thread#interrupt interrupted} while
         * acquiring the write lock,
         *
         * </ul>
         *
         * then {@link InterruptedException} is thrown and the current
         * thread's interrupted status is cleared.
         *
         * <p>If the specified waiting time elapses then the value
         * {@code false} is returned.  If the time is less than or
         * equal to zero, the method will not wait at all.
         *
         * <p>In this implementation, as this method is an explicit
         * interruption point, preference is given to responding to
         * the interrupt over normal or reentrant acquisition of the
         * lock, and over reporting the elapse of the waiting time.
         *
         * @param timeout the time to wait for the write lock
         * @param unit the time unit of the timeout argument
         *
         * @return {@code true} if the lock was free and was acquired
         * by the current thread, or the write lock was already held by the
         * current thread; and {@code false} if the waiting time
         * elapsed before the lock could be acquired.
         *
         * @throws InterruptedException if the current thread is interrupted
         * @throws NullPointerException if the time unit is null
         */
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
//            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        try {


    String splitStr = "_lock_";


    if (lockName.contains(splitStr))


    {
//     throw new LockException("lockName can not contains \\u000B");
    }


    myZnode = zk.create(root + "/" + lockName + splitStr, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE,
    CreateMode.EPHEMERAL_SEQUENTIAL);


    System.out.println(myZnode + " is created ");


    List<String> subNodes = zk.getChildren(root, false);


    List<String> lockObjNodes = new ArrayList<String>();


    for (String node : subNodes) {


    String _node = node.split(splitStr)[0];


    if (_node.equals(lockName)) {


    lockObjNodes.add(node);


    }


    }


    Collections.sort(lockObjNodes);


    System.out.println(myZnode + "==" + lockObjNodes.get(0));


    if (myZnode.equals(root + "/" + lockObjNodes.get(0))) {


    return true;


    }


    String subMyZnode = myZnode.substring(myZnode.lastIndexOf("/") + 1);


    waitNode = lockObjNodes.get(Collections.binarySearch(lockObjNodes, subMyZnode) - 1);


    } catch (KeeperException e) {


    e.printStackTrace();


//     throw new LockException(e);


    } catch (InterruptedException e) {


    e.printStackTrace();


//     throw new LockException(e);


    }


    return false;
        }


        /**
         * Attempts to release this lock.
         *
         * <p>If the current thread is the holder of this lock then
         * the hold count is decremented. If the hold count is now
         * zero then the lock is released.  If the current thread is
         * not the holder of this lock then {@link
         * IllegalMonitorStateException} is thrown.
         *
         * @throws IllegalMonitorStateException if the current thread does not
         * hold this lock
         */
        public void unlock() {
//            sync.release(1);
        try {


    System.out.println("unlock " + myZnode);


    zk.delete(myZnode, -1);


    myZnode = null;


    zk.close();


    } catch (InterruptedException e) {


    e.printStackTrace();


    } catch (KeeperException e) {


    e.printStackTrace();


    }
        }


        /**
         * Returns a {@link Condition} instance for use with this
         * {@link Lock} instance.
         * <p>The returned {@link Condition} instance supports the same
         * usages as do the {@link Object} monitor methods ({@link
         * Object#wait() wait}, {@link Object#notify notify}, and {@link
         * Object#notifyAll notifyAll}) when used with the built-in
         * monitor lock.
         *
         * <ul>
         *
         * <li>If this write lock is not held when any {@link
         * Condition} method is called then an {@link
         * IllegalMonitorStateException} is thrown.  (Read locks are
         * held independently of write locks, so are not checked or
         * affected. However it is essentially always an error to
         * invoke a condition waiting method when the current thread
         * has also acquired read locks, since other threads that
         * could unblock it will not be able to acquire the write
         * lock.)
         *
         * <li>When the condition {@linkplain Condition#await() waiting}
         * methods are called the write lock is released and, before
         * they return, the write lock is reacquired and the lock hold
         * count restored to what it was when the method was called.
         *
         * <li>If a thread is {@linkplain Thread#interrupt interrupted} while
         * waiting then the wait will terminate, an {@link
         * InterruptedException} will be thrown, and the thread's
         * interrupted status will be cleared.
         *
         * <li> Waiting threads are signalled in FIFO order.
         *
         * <li>The ordering of lock reacquisition for threads returning
         * from waiting methods is the same as for threads initially
         * acquiring the lock, which is in the default case not specified,
         * but for <em>fair</em> locks favors those threads that have been
         * waiting the longest.
         *
         * </ul>
         *
         * @return the Condition object
         */
        public Condition newCondition() {
return null;
//            return sync.newCondition();
        }


        /**
         * Returns a string identifying this lock, as well as its lock
         * state.  The state, in brackets includes either the String
         * {@code "Unlocked"} or the String {@code "Locked by"}
         * followed by the {@linkplain Thread#getName name} of the owning thread.
         *
         * @return a string identifying this lock, as well as its lock state
         */
        public String toString() {
return lockName;
//            Thread o = sync.getOwner();
//            return super.toString() + ((o == null) ?
//                                       "[Unlocked]" :
//                                       "[Locked by thread " + o.getName() + "]");
        }


        /**
         * Queries if this write lock is held by the current thread.
         * Identical in effect to {@link
         * ReentrantReadWriteLock#isWriteLockedByCurrentThread}.
         *
         * @return {@code true} if the current thread holds this lock and
         *         {@code false} otherwise
         * @since 1.6
         */
        public boolean isHeldByCurrentThread() {
return false;
//            return sync.isHeldExclusively();
        }


        /**
         * Queries the number of holds on this write lock by the current
         * thread.  A thread has a hold on a lock for each lock action
         * that is not matched by an unlock action.  Identical in effect
         * to {@link ReentrantReadWriteLock#getWriteHoldCount}.
         *
         * @return the number of holds on this lock by the current thread,
         *         or zero if this lock is not held by the current thread
         * @since 1.6
         */
        public int getHoldCount() {
return sessionTimeout;
//            return sync.getWriteHoldCount();
        }



    }


@Override
public DistributedReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }


@Override
public Lock readLock() {
// TODO Auto-generated method stub
return null;
}


@Override
public void process(WatchedEvent event) {
if (this.latch != null) {


this.latch.countDown();


}

}
    private static boolean waitForLock(String lower, long waitTime)


  throws InterruptedException, KeeperException {


  Stat stat = zk.exists(root + "/" + lower, true);


  if (stat != null) {


  System.out.println("Thread " + Thread.currentThread().getId() + " waiting for " + root + "/" + lower);


  latch = new CountDownLatch(1);


  latch.await(waitTime, TimeUnit.MILLISECONDS);


  latch = null;


  }


  return true;


  }



}


测试类

ReadWriteLockTest.java

package com.ujia.wb.zk.lock;


import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


public class ReadWriteLockTest {
public static void main(String[] args) {
   final ReadWrite rw = new ReadWrite();
   for (int i = 0; i < 3; i++) {
     new Thread() {
       public void run() {
         while (true) {
           rw.read();
         }
       }
 
     }.start();
 
     new Thread() {
       public void run() {
         while (true) {
           rw.write(new Random().nextInt(10000));
         }
       }
 
     }.start();
   }
 
 }
}
 
/**
* 读和写要互斥,因此要把它们放在同一个类中
*
* @author Administrator
*
*/
class ReadWrite {
 private Object data = null;//共享数据,只能有一个线程写该数据,但可以有多个线程同时读该数据。
 ReadWriteLock rwl = new ReentrantReadWriteLock();
 
 /**
  * 读数据
  */
 public void read() {
     
   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();
   }
     
 }
 
 /**
  * 写数据
  *
  * @param data
  */
 public void write(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();
   }
 
 }
}


TestLock.java


package com.ujia.wb.zk.lock;


import java.util.Date;


public class TestLock implements Runnable {


public static void main(String[] args) {


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


Thread ad = new Thread(new TestLock());


ad.start();


}


}


@Override


public void run() {


DistributedLock lock = null;


try {


System.out.println("线程开启:" + Thread.currentThread().getId());


// 多个锁用“,” 分隔开


// lock = new
// DistributedLock("10.168.128.113:2181,10.168.173.159:2181",
// "amount");


// Thread.sleep(1000);


lock = new DistributedLock("localhost:2181", "testLock");


lock.lock();


System.out.println("线程:" + Thread.currentThread().getId() + "在" + new Date().getTime() + "时间获得锁");


// Thread.sleep(4000);


System.out.println("===Thread " + Thread.currentThread().getId() + " running");


} catch (Exception e) {


e.printStackTrace();


} finally {


if (lock != null) {


System.out.println("线程:" + Thread.currentThread().getId() + "在" + new Date().getTime() + "释放锁");


lock.unlock();


}


}


}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基于 ZooKeeper 实现分布式锁的 Java 代码示例: ```java import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; public class DistributedLock { private static final String LOCK_ROOT_PATH = "/locks"; private static final String LOCK_NODE_PREFIX = "lock-"; private final String lockPath; private final ZooKeeper zk; private String lockNode; private CountDownLatch lockAcquiredSignal; public DistributedLock(String zookeeperUrl, String lockPath) throws Exception { this.lockPath = LOCK_ROOT_PATH + "/" + lockPath; this.zk = new ZooKeeper(zookeeperUrl, 3000, null); ensureLockPathExists(); } public void lock() throws Exception { while (true) { try { lockNode = zk.create(lockPath + "/" + LOCK_NODE_PREFIX, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); lockAcquiredSignal = new CountDownLatch(1); waitForLock(); return; } catch (KeeperException.NodeExistsException e) { // node already exists, wait for the previous holder to release the lock waitForPreviousLock(); } } } public void unlock() throws Exception { zk.delete(lockNode, -1); lockNode = null; lockAcquiredSignal.countDown(); } private void ensureLockPathExists() throws Exception { if (zk.exists(lockPath, false) == null) { zk.create(lockPath, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } private void waitForPreviousLock() throws Exception { List<String> lockNodes = zk.getChildren(lockPath, false); Collections.sort(lockNodes); int currentLockIndex = lockNodes.indexOf(lockNode.substring(lockPath.length() + 1)); if (currentLockIndex <= 0) { throw new IllegalStateException("Lock node not found: " + lockNode); } String previousLockNode = lockPath + "/" + lockNodes.get(currentLockIndex - 1); Stat previousLockStat = zk.exists(previousLockNode, new LockWatcher()); if (previousLockStat != null) { lockAcquiredSignal.await(); } } private void waitForLock() throws Exception { List<String> lockNodes = zk.getChildren(lockPath, false); Collections.sort(lockNodes); int currentLockIndex = lockNodes.indexOf(lockNode.substring(lockPath.length() + 1)); if (currentLockIndex == 0) { // this is the first lock node, lock acquired return; } String previousLockNode = lockPath + "/" + lockNodes.get(currentLockIndex - 1); Stat previousLockStat = zk.exists(previousLockNode, new LockWatcher()); if (previousLockStat == null) { // previous lock node has been deleted, lock acquired return; } lockAcquiredSignal.await(); } private class LockWatcher implements Watcher { @Override public void process(WatchedEvent event) { if (event.getType() == Event.EventType.NodeDeleted) { lockAcquiredSignal.countDown(); } } } } ``` 使用示例: ```java DistributedLock lock = new DistributedLock("localhost:2181", "my-lock"); lock.lock(); try { // critical section } finally { lock.unlock(); } ``` 该示例代码使用了 ZooKeeper 的临时顺序节点来实现分布式锁。当多个节点同时请求锁时,它们会在 ZooKeeper 中创建一个临时顺序节点,并按照节点名称的顺序等待前面的节点释放锁。当锁被释放时,它会通知等待的节点,让它们尝试重新获得锁。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值