Redis本身是单线程线程安全的内存数据库,但是不代表你的使用就是线程安全的

网上一个错误示例:https://www.cnblogs.com/Simeonwu/p/7881100.html,部分代码如下:

package com.me.config;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * Project: me
 * Package: com.me.config
 * Date: 2017/11/22 19:30
 * Author: Simeon
 */

class Demo extends Thread
{
    public void run()
    {
        Jedis jedis1 = new Jedis();
        for (int i=0;i<100;i++){
            int num = Integer.parseInt(jedis1.get("num"));// 1: 代码行1
            num = num + 1; // 2: 代码行2
            jedis1.set("num",num+"");
            System.out.println(jedis1.get("num"));
        }
    }

}

public class test{

    public static void main(String... args){
        Jedis jedis = new Jedis();
        jedis.set("num","1");
        new Demo().start();
        new Demo().start();
    }

}

 

如代码所示,例如当线程1在代码行读取数值为99时候,此时线程2页执行读取操作也是99,随后同时执行num=num+1,之后更新,导致一次更新丢失,这就是这个代码测试的错误之处。所以Redis本身是线程安全的,但是你还需要保证你的业务必须也是线程安全的。

 

注意:千万不要以为原子操作是线程安全的,原子操作只能保证命令全执行或者全不执行,并不会保证线程安全操作。例如数据库中的事务就是原子的,依旧还需要提供并发控制!!!!

 

原子性操作是否线程安全?

原文:https://stackoverflow.com/questions/14370575/why-are-atomic-operations-considered-thread-safe

 

1.原子操作是针对访问共享变量的操作而言的。涉及局部变量访问的操作无所谓是否原子的。
2.原子操作是从该操作的执行线程以外的线程来描述的,也就是说它只有在多线程环境下才有意义。


原子操作得“不可分割”包括两层含义
1.访问(读、写)某个共享变量的操作从其执行线程以外的任何线程来看,该操作要么已经执行结束要么尚未发生,
即其他线程不会“看到”该操作执行了部分的中间效果。
2.访问同一组共享变量的原子操作是不能够被交错的。

 

 

 

此原子性与数据库原子性有区别:最主要区别是数据库的原子性,可以被其他线程看见中间状态,否则就不会有隔离级别的事了。

posted @ 2018-08-27 20:26  bf378  阅读(6833)  评论(1编辑  收藏  举报