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 lockContext = new  ThreadLocal ();

        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();

        }

}

你可能感兴趣的:(redis实现分布式锁)