美文网首页
1、redis不能保证你的代码线程安全

1、redis不能保证你的代码线程安全

作者: 欧阳的博客 | 来源:发表于2021-01-25 18:36 被阅读0次

    总结:redis的每个操作是原子操作,但是在java代码中组合起来的redis操作不是原子操作,因此需要借用redis来实现分布式锁,解决并发问题。

    虽然redis的操作是原子操作,但如果在java中分步操作的话,依旧会出现并发问题。
    例如:先获取redis中的number,加1后再放回redis,如果10个线程同时处理的话,会出现并发问题。

    public class test {
        public static void main(String[] args) {
            for (int i = 0; i < 10; i++) {
                Thread thread1 = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Redis ru = new Redis();
                        //获取redis的值
                        Integer number= ru.getInteger("number");
                        number++;
                        //加一再放回redis
                        ru.set("number",number.toString());
                        System.out.println(Thread.currentThread().getName() +"---->result:" +  number) ;
                    }
                });
                thread1.start();
            }
        }
    
    }
    

    结果为

    image.png
    在redis中的数据如图
    image.png
    由于初始number为0,运行10次后,应该为10,但是数据库中的number值为1,出现了错误。因为虽然redis的set和get操作是原子操作,但是在java代码中这两步分开了 ,所以还是没法兼容多线程的操作。后面我们会慢慢介绍如何通过redis的原子操作解决多线程并发的问题。

    附java中操作jedis的代码:

    package com.dazhiyouqiu.api;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
    
    public class Redis {
    
            private Jedis jedis;
            private JedisPool jedisPool;
    
            public Redis() {
                initialPool();
                jedis = jedisPool.getResource();
            }
    
    
            private void initialPool() {
                JedisPoolConfig config = new JedisPoolConfig();
                config.setMaxWaitMillis(100000l);
                config.setMaxIdle(20);
                config.setTestOnBorrow(false);
    
                jedisPool = new JedisPool(config, "127.0.0.1", 6379,100000);
    
            }
    
    
            public String get(String key) {
                String getStr = jedis.get(key);
                return getStr;
            }
    
            public Integer getInteger(String key){
                String re =jedis.get(key);
                return re==null?0:Integer.valueOf(re);
            }
    
            public String set(String key, String value) {
                String setStr = jedis.set(key, value);
                return setStr;
            }
    
            public Long delete(String key){
                Long re =jedis.del(key);
                return re;
            }
    
        // NX是不存在时才set, XX是存在时才set, EX是秒,PX是毫秒
        public String set(String key, String value,long expireSecond) {
    
            String setStr = jedis.set(key, value,"NX","EX",expireSecond);
            return setStr;
        }
    
    }
    

    相关文章

      网友评论

          本文标题:1、redis不能保证你的代码线程安全

          本文链接:https://www.haomeiwen.com/subject/ogyizktx.html