五.Curator实现分布式锁

来源:互联网 发布:淘宝新版怎样发布宝贝 编辑:程序博客网 时间:2024/05/20 02:54

        InterProcessMutex:全局可重入锁,客户端都可以请求锁,并且同一个客户端在拥有锁的同时,可以多次获取,不会被阻塞。客户端在拥有锁的同时,可以多次获取,不会被阻塞。

package DistributeLock;import java.util.concurrent.TimeUnit;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.recipes.locks.InterProcessMutex;/** * 这个类负责请求锁,使用资源,释放锁这个完整的访问流程 * */public class ExampleClientThatLocks{    private final InterProcessMutex lock;//全局可重入锁    private final FakeLimitedResource resource;//共享资源    private final String clientName;    public ExampleClientThatLocks(CuratorFramework client,String lockPath, FakeLimitedResource resource, String clientName)    {        this.lock = new InterProcessMutex(client, lockPath);        this.resource = resource;        this.clientName = clientName;    }    public void doWork(long time,TimeUnit unit) throws Exception{        //尝试获取锁,如果无法获取锁,抛出异常        if(!lock.acquire(time, unit)){            throw new IllegalStateException(clientName + "不能获取锁");        }        System.out.println(clientName +"获得了锁");        if(!lock.acquire(time, unit)){            throw new IllegalStateException(clientName + "不能再次获取锁");        }        System.out.println(clientName +"再次获得了锁(重入功能)");        try{            resource.use();        }finally{            System.out.println(clientName + "释放了锁");            lock.release();            lock.release();        }            }        }
package DistributeLock;import java.util.concurrent.atomic.AtomicBoolean;/** * 模拟共享资源,这个资源期望只能单线程访问,否则会有并发问题(走到抛异常的逻辑) * <br> */public class FakeLimitedResource {    private final AtomicBoolean inUse = new AtomicBoolean(false);    public void use() throws InterruptedException {        /**         * inUse.compareAndSet(false, true)表示:先检测当前值是否为false,如果为false,就更新为true         * 如果多个线程执行这个方法,在无锁的情况下,由于下面睡了一段时间,所以有些线程会走到抛异常的地方         */        if (!inUse.compareAndSet(false, true)) {             throw new IllegalStateException("Needs to be used by one client at a time");        }        try {            Thread.sleep(5000);        } finally {            inUse.set(false);        }    }    public void read(){        System.out.println(inUse.get());    }}
package DistributeLock;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import org.apache.curator.RetryPolicy;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.CuratorFrameworkFactory;import org.apache.curator.retry.ExponentialBackoffRetry;import org.apache.curator.test.TestingServer;import org.apache.curator.utils.CloseableUtils;/** *可重入锁InterProcessMutex例子  * */public class InterProcessMutexExample{       private static final String PATH = "/examples/locks";    public static void main(String[] args) throws Exception    {        //共享资源        final FakeLimitedResource resource = new FakeLimitedResource();        //有50个线程的线程池        ExecutorService service = Executors.newFixedThreadPool(10);                RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);               //10个线程,模拟10个客户端        for(int i=0;i<10;++i){            final int index = i;            Callable<Void> task = new Callable<Void>()            {                public Void call() throws Exception                {                    //2.通过工厂建立连接                    CuratorFramework client = CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181")                            .sessionTimeoutMs(5000)                            .retryPolicy(retryPolicy)                            .build();                    try                    {                        client.start();                        ExampleClientThatLocks example = new ExampleClientThatLocks(client, PATH, resource,"client" + index);                        //每个客户端重复5次任务                        for(int j=0;j<5;++j){                            example.doWork(10, TimeUnit.SECONDS);                        }                    }                    catch (Exception e)                    {                       e.printStackTrace();                    }finally{                        CloseableUtils.closeQuietly(client);//关闭该客户端                    }                                        return null;                }            };            service.submit(task);        }        service.shutdown();            }}

  代码也很简单,生成10个client, 每个client重复执行5次 请求锁–访问资源–释放锁的过程。每个client都在独立的线程中。结果可以看到,锁是随机的被每个客户端实例排他性的使用。既然是可重用的,你可以在一个线程中多次调用acquire,在线程拥有锁时它总是返回true。 

  你不应该在多个线程中用同一个InterProcessMutex,你可以在每个线程中都生成一个InterProcessMutex实例,它们的path都一样,这样它们可以共享同一个锁。


InterProcessSemaphoreMutex:不可重入锁
  这个锁和上面的相比,就是少了Reentrant的功能,也就意味着它不能在同一个线程中重入。 这个类是InterProcessSemaphoreMutex。使用方法和上面的类类似。

  我们将上面的例子修改一下,测试一下它的重入,修改ExampleClientThatLocks.doWork,连续两次acquire。现在第二次acquire进不去了。

package curatorExample.DistributeLock;import java.util.concurrent.TimeUnit;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.recipes.locks.InterProcessMutex;import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;/** * 测试不可重入锁 * 这个类负责请求锁,使用资源,释放锁这个完整的访问流程 * */public class ExampleClientThatLocks2{    private final InterProcessSemaphoreMutex lock;//全局可重入锁    private final FakeLimitedResource resource;//共享资源    private final String clientName;    public ExampleClientThatLocks2(CuratorFramework client,String lockPath, FakeLimitedResource resource, String clientName)    {        this.lock = new InterProcessSemaphoreMutex(client, lockPath);//不可重入的锁        this.resource = resource;        this.clientName = clientName;    }    public void doWork(long time,TimeUnit unit) throws Exception{        //尝试获取锁,如果无法获取锁,抛出异常        if(!lock.acquire(time, unit)){            throw new IllegalStateException(clientName + "不能获取锁");        }        System.out.println(clientName +"获得了锁");        //现在这里不能重入了        if(!lock.acquire(time, unit)){            throw new IllegalStateException(clientName + "不能再次获取锁");        }        System.out.println(clientName +"再次获得了锁(重入功能)");        try{            resource.use();        }finally{            System.out.println(clientName + "释放了锁");            lock.release();            lock.release();        }            }}


InterProcessReadWriteLock:可重入读写锁

  类似JDK的ReentrantReadWriteLock. 一个读写锁管理一对相关的锁。 一个负责读操作,另外一个负责写操作。读操作在写锁没被使用时可同时由多个进程使用,而写锁使用时不允许读 (阻塞)。 此锁是可重入的。一个拥有写锁的线程可重入读锁,但是读锁却不能进入写锁。 这也意味着写锁可以降级成读锁, 比如请求写锁 —>读锁 —->释放写锁。从读锁升级成写锁是不成的。

  主要由两个类实现:

         InterProcessReadWriteLock
         InterProcessLock

  使用时首先创建一个InterProcessReadWriteLock实例,然后再根据你的需求得到读锁或者写锁, 读写锁的类型是InterProcessLock。 
   public InterProcessLock readLock()
        public InterProcessLock writeLock()

package curatorExample.DistributeLock;import java.util.Random;import java.util.concurrent.TimeUnit;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.recipes.locks.InterProcessLock;import org.apache.curator.framework.recipes.locks.InterProcessMutex;import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;public class ExampleClientReadWriteLocks{    private final InterProcessReadWriteLock lock;    private final InterProcessLock readLock;    private final InterProcessLock writeLock;    private final FakeLimitedResource resource;    private final String clientName;    public ExampleClientReadWriteLocks(CuratorFramework client, String lockPath, FakeLimitedResource resource, String clientName) {        this.resource = resource;        this.clientName = clientName;        lock = new InterProcessReadWriteLock(client, lockPath);        readLock = lock.readLock();        writeLock = lock.writeLock();    }    public void doWork(long time,TimeUnit unit) throws Exception{        Random rand = new Random();        int random_data = rand.nextInt();        try{            if(random_data %10 == 0){                //尝试获取写锁,                if(!writeLock.acquire(time, unit)){                    throw new IllegalStateException(clientName + "不能获得写锁");                }                System.out.println(clientName + " 获得了写锁");                  resource.use();              }else{                //尝试获取读锁                if(!readLock.acquire(time, unit)){                    throw new IllegalStateException(clientName + "不能获得读锁");                }                System.out.println(clientName + " 获得了读锁");                resource.read();                            }         }finally{            System.out.println(clientName + " 释放锁");            if(writeLock.isAcquiredInThisProcess())                writeLock.release();             if(readLock.isAcquiredInThisProcess())                readLock.release();         }                                    }}
package curatorExample.DistributeLock;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import org.apache.curator.RetryPolicy;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.CuratorFrameworkFactory;import org.apache.curator.retry.ExponentialBackoffRetry;import org.apache.curator.utils.CloseableUtils;public class InterProcessReadWriteLockExample{    private static final String PATH = "/examples/locks";    public static void main(String[] args) throws Exception    {        //共享资源        final FakeLimitedResource resource = new FakeLimitedResource();        //有10个线程的线程池        ExecutorService service = Executors.newFixedThreadPool(10);                RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);               //10个线程,模拟10个客户端        for(int i=0;i<10;++i){            final int index = i;            Callable<Void> task = new Callable<Void>()            {                public Void call() throws Exception                {                    //2.通过工厂建立连接                    CuratorFramework client = CuratorFrameworkFactory.builder().connectString("192.168.10.110:2181,192.168.10.111:2181,192.168.10.112:2181")                            .sessionTimeoutMs(5000)                            .retryPolicy(retryPolicy)                            .build();                    try                    {                        client.start();                        ExampleClientReadWriteLocks example = new ExampleClientReadWriteLocks(client, PATH, resource,"client" + index);                        //每个客户端重复5次任务                        for(int j=0;j<5;++j){                            example.doWork(10, TimeUnit.SECONDS);                        }                    }                    catch (Exception e)                    {                       e.printStackTrace();                    }finally{                        CloseableUtils.closeQuietly(client);//关闭该客户端                    }                                        return null;                }            };            service.submit(task);        }        service.shutdown();    }}



阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 上海可迪食品有限公司 上海迪尼斯 上海阿纳迪酒店 上海迪士 上海国金 上海金属回收 上海黄金回收价格 上海金交所黄金实时行情 金上海 上海金铸坊珠宝 上海生育金领取 上海失业金领取条件 上海失业金多少钱一个月 上海黄金交易所开户入金多少 上海金川镍今日价格 上海金古源大酒店 上海崇明金平农家乐 上海金价格 硬金上海 黄金回收价格今天多少一克 现在黄金回收价格 今天黄金回收多少钱一克 旧黄金回收价格 9999黄金回收价格 高价回收黄金多少钱一克 中国黄金回收价格表 中国黄金回收价格 2016黄金回收价格 金价回收多少钱一克 黄金收购多少钱一克 金子回收多少钱一克 金店回收金子多少钱一克 黄金回购价格 金银回收价格 现在黄金回收多钱一克 黄金实时 上海期货铜价格行情 上海铜门 上海铜镜鉴定 上海期货铜 上海今日废铜价格行情