i++线程安全吗,如何让i++线程安全

1. i++线程安全吗

1.1把数据直接放到类里面

@Controller
public class  A{
    private int value =0;
    
    
     @ApiOperation(value = "i++是否线程安全测试接口", notes = "是否线程安全测试接口")
    @RequestMapping(value = "/i", method = RequestMethod.GET)
    @ResponseBody
    public int i() {
        System.out.println("-----------之前:"+value);
        value++;
        System.out.println("============I++之后的值:"+value);
        System.out.println();
        System.out.println();

    return value;
    }
}
如果你用模拟一千个线程来访问:最后的结果是1000
但是每次读的数据不一定一样,看代码打印结果:
-----------之前:516
============I++之后的值:998
-----------之前:516
============I++之后的值:999
-----------之前:493
============I++之后的值:1000 
I++其实线程不安全
自增操作看起来是一个单一的操作,但是事实上,它分为3个独立的操作
1. 读取值 2. +1  ,3. 写入新值

1.2如果把Value存到MySQL或者redis里面

  @ApiOperation(value = "把值放到redis或者MySQL里面,i++是否线程安全测试接口", notes = "是否线程安全测试接口")
    @RequestMapping(value = "/redisZZ", method = RequestMethod.GET)
    @ResponseBody
    public int redisIvalue() {
        int value1 = Integer.parseInt(redisManager.getStr("zizeng"));
        System.out.println("-----------之前:"+value1);
        value1++;
        redisManager.setStr("zizeng",String.valueOf(value1));
        System.out.println("============I++之后的值:"+value1);
        System.out.println();
        System.out.println();

        return value1;
    }
其结果和放到类里面的差不多,也是线程不安全的
============I++之后的值:296
-----------之前:296
-----------之前:295
-----------之前:291
-----------之前:295
-----------之前:295
============I++之后的值:295

2. 让自增安全

volatile不是原子性的,进行++操作不是安全的

在方法里面添加syschronized关键字

 public synchronized int i() {
        System.out.println("-----------之前:"+value);
        value++;
        System.out.println("============I++之后的值:"+value);
        System.out.println();
        System.out.println();

    return value;
    }

猜你喜欢

转载自blog.csdn.net/qq_39455116/article/details/86633417
i++