三、curator recipes之共享的可重入读写锁

简介

curator实现了跨JVM的可重入读写互斥锁。它使用zookeeper去进行加锁,所以指定相同路径的处理线程将会基于“公平锁”的机制去竞争锁资源。

读写锁包含了读锁、写锁两个,它们的互斥关系如下:

1)读写互斥;

2)写写互斥;

3)读读不互斥。

重入性:读写锁是可以重入的,意味着你获取了一次读锁/写锁,那么你可以再次获取。但是要记得最后释放锁,获取了几次就得释放几次。

降级/升级:写锁可以降级成读锁,但是读锁不能升级成写锁否则会导致循环等待最终死锁。

官方文档:http://curator.apache.org/curator-recipes/shared-reentrant-read-write-lock.html

javaDoc:http://curator.apache.org/apidocs/org/apache/curator/framework/recipes/locks/InterProcessReadWriteLock.html

相关接口:InterProcessLock

实现类:InterProcessReadWriteLock

依赖

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

示例

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 LocksDemo {
    private static CuratorFramework client;
    private static InterProcessMutex readLock;
    private static InterProcessMutex writeLock;

    static {
        client = CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181").retryPolicy(new ExponentialBackoffRetry(3000, 1)).build();
        // 调用启动
        client.start();
        // 获取读写锁
        InterProcessReadWriteLock lock = new InterProcessReadWriteLock(client, "/user");
        readLock = lock.readLock();
        writeLock = lock.writeLock();
    }

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            public void run() {
                System.out.println("线程1启动");
                try {
                    // 先获取读锁
                    readLock.acquire();
                    System.out.println("获取读锁" + System.currentTimeMillis());
                    Thread.sleep(3000);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        // 释放读锁
                        readLock.release();
                        System.out.println("释放读锁" + System.currentTimeMillis());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        System.out.println("主线程休眠2秒,让子线程获取读锁");
        Thread.sleep(2000);
        // 争抢写锁,这时候读锁还没有释放
        writeLock.acquire();
        // 3秒钟以后,读锁释放了,写锁获取,最终写锁也释放
        System.out.println("获取写锁" + System.currentTimeMillis());
        writeLock.release();
        System.out.println("释放写锁" + System.currentTimeMillis());
        // 最后关闭
        client.close();
    }
}

我们先拿到一个framework,然后创建一个InterProcessReadWriteLock,就可以通过它拿到读写锁实例对象了。

在代码中,子线程获取了读锁,然后休眠3秒,而主线程这期间想要获取写锁,就得阻塞等待读锁释放,然后才能获取写锁。

 

posted @ 2018-09-12 16:42  __lay  阅读(630)  评论(0编辑  收藏  举报