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.訪問同一組共享變量的原子操作是不能夠被交錯的。

 

 

 

此原子性與數據庫原子性有區別:最主要區別是數據庫的原子性,可以被其他線程看見中間狀態,否則就不會有隔離級別的事了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM