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;
}