在工作中,发现之前留下来的代码遗留有一个问题:代码内有一个多线程的操作,在高并发下,出现部分数据丢失错乱。
由于不便展示源代码,写了一个Demo演示相似情况。
问题的原因,及其解决方式、结论
- 原因:是由于多线程操作同一个对象,Thread-1操作修改对象时,会导致Thread-2内的对象也发生改变。
- 解决方式:在多线程的入口处,拷贝(
可根据具体业务逻辑选择深拷贝与浅拷贝
)对象进行传递。 - 结论:Controller层的参数对象在不同的请求中不共享,而若往下层传递同一个对象则会共享同一个对象。
演示Demo
Controller层
package pro.eddievim.threads;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @author eddie
* @date 2020/8/12 8:50
*/
@RestController
public class Controller {
@Autowired
private Service service;
@RequestMapping("/enter")
public int enter(@RequestParam Map<String, String> map) {
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("~~~enter~~~");
// 打印对象的内存地址
System.out.println("\tmap地址:" + System.identityHashCode(map));
service.fun(map);
System.out.println("~~~enter~~~");
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
return 0;
}
@RequestMapping("/newEnter")
public int newEnter(@RequestParam Map<String, String> map) {
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("~~~newEnter~~~");
// 打印对象的内存地址
System.out.println("\tmap地址:" + System.identityHashCode(map));
service.