redis实现分布式锁

一、什么是线程安全

        当多个线程访问某个类时,不管运行时环境采用何种类,调度方式或者这些线程将如何交替执行,并且在主要代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么这个类就是线程安全的。

        锁的使用能使并行执行的代码变成串行执行,从而实现线程安全。

二、如何优化锁?

        1、缩小锁的范围。

        2、减小锁的粒度。

        3、使用锁分段技术。

三、锁的种类

        1、公平锁:synchronized,ReentrantLock。

        2、非公平锁:ReentrantLock,CAS(主要用于竞争量不大的情况,不要用在竞争激烈的情况)。

        3、独享锁:synchronized,ReentrantLock。

        4、共享锁:semaphore。

四、一个分布式锁需要满足的特性

        1、互斥性

        在任意时刻只有一个客户端可以获取锁。

        2、防死锁

        即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续客户端能加锁,加一个有效时间。

        3、持锁人解锁

        加锁和解锁必须是同一个客户端,客户端不能把别人加的锁给解了。

        4、可重入

        当一个客户端获取锁对象之后,这个客户端可以再次获取该对象上的锁。

五、加锁解锁的流程

加解锁流程

 六、分布式锁的算法实现

分布式锁的算法实现

七、上代码

public class RedisDistributedLock implements Lock{

        private ThreadLocal<String> lockContext = new  ThreadLocal<String> ();

        private long time = 100 ;

        private Thread exclusiveOwnerThread ;

        public  RedisDistributedLock (){

        }

        //阻塞式获取锁

        public void lock() {

                while(!tryLock()){

                        try{

                            Thread.sleep(time);

                        }catch(InterruptedException e){

                            e.printStrackStace();

                        }

                }

        }

        public boolean tryLock(){

                return  tryLock(time , TimeUnit.MILLSECOND);

        }

        private boolean  tryLock(long time , TimeUnit  timeUnit){

                String id = UUID.randomUUID().toString();

                Thread t = thread.currentThread();

                Jedis jedis = RedisClient.getClient();

                if(jedis.setnx("redis",id)==1){

                        jedis.pexpire( "redis" , timeUnit.toMills(time) );

                        lockContext.set(id);

                        setExclusiveOwnerThread(t);

                        return true;

                }else if( exclusiveOwnerThread==t  ){

                        return true;

                }

                return false;

        }

        public void unLock(){

                String script = null;

                try{

                    Jedis jedis =  RedisClient.getClient();

                     script  = inputStream2String(getClass().getSourceAsStream("/redis. script "));

                    if(lockContext.get()==null){

                            return ;

                    }

                    jedis.eval( script, Arrays.asList("redis"), Arrays.asList(lockContext.get()) );    

                    lockContext.remove();

                }catch(Exception e){

                      e.printStrackTrace();

                }

        }

        public void lockInterruptibly() throws InterruptedException{

                if(Thread.interrupted())

                    throws  new InterruptedException ();

                while(! tryLock()){

                     Thread.sleep(time);

                }

        }

        private String  inputStream2String (InputStream in) throws IOException{

                StringBuffer out = new  StringBuffer();

                byte[] b = new  byte[1024];

                for(int n;(n=in.read(b))!=-1;){

                        out.append(new String(0,n));

                }

                return out.toString();

        }

}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 目前实现分布式锁的方式主要有数据库、Redis和Zookeeper三种,本文主要阐述利用Redis的相关命令来实现...
    Aldeo阅读 2,165评论 0 6
  • 前言 单机环境下我们可以通过JAVA的Synchronized和Lock来实现进程内部的锁,但是随着分布式应用和集...
    Java黎先生阅读 844评论 0 1
  • 1.何为分布式锁 java synchronized和Reentrantlock等只能保证同一个JVM进程...
    琥珀灬阅读 796评论 0 8
  • 2018-08-22 姓名:韩兴国 公司:上海东方星教育 【六项精进打卡第87天】 【知~学习】 《大学》2遍,共...
    韩兴国阅读 235评论 0 0
  • 第三章:极寒之地,有美人兮。 白色的。依旧是空荡荡的白。大片的白色,令人晕眩。自己怎么出现在这里?他不明白。 面对...
    狗蛋先生阅读 483评论 1 1

友情链接更多精彩内容