多线程操作带来数据不一致情况分析,简单demo。
public class Object_IS {
private Student_Object so = new Student_Object("张三", 123);
public static void main(String[] args) throws InterruptedException {
Object_IS os = new Object_IS();
os.test1();
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(() -> {
os.so = new Student_Object("李四", 900);
});
thread.start();
// os.test1();
os.test2();
System.out.println("-------------------------------");
}
}
public void test2() throws InterruptedException {
String name = this.so.getName();
//为了使问题暴漏,故意睡眠
Thread.sleep(100);
Integer code = this.so.getCode();
System.out.println("name:" + name + " code: " + code);
}
public void test1() {
//相当于保持快照
Student_Object so = this.so;
String name = so.getName();
Integer code = so.getCode();
System.out.println("name:" + name + " code: " + code);
}
}
class Student_Object {
private String name;
private Integer code;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public Student_Object(String name, Integer code) {
this.name = name;
this.code = code;
}
@Override
public String toString() {
return "Student_Object{" + "name='" + name + '\'' + ", code=" + code + '}';
}
}
代码分析:
首先main方法中创建了Object_IS对象,对象中包含另外一个对象Student_Object (初始值: name = “张三”,code = 123);
test1() 方法:
public void test1() {
//相当于保持快照
Student_Object so = this.so;
String name = so.getName();
Integer code = so.getCode();
System.out.println("name:" + name + " code: " + code);
}
test1中:Student_Object so = this.so; 如蓝线所示,这样即使os中的so发生了变化,也不会影响方法中下面操作该对象的值。
test2() 方法:
test2中使用的使this.so 获取当前的值,也即永远可以获取最新的值,可能会带来操作对象不一致的情况。如下: 在方法执行完this.so.getName();后,一个线程改变了this.so的“指向”,指向了一个新的对象,再执行this.so.getCode();则获取的是最新对象的值,而不是原有对象的值。
public void test2() throws InterruptedException {
String name = this.so.getName();
//为了使问题暴漏,故意睡眠
Thread.sleep(100);
Integer code = this.so.getCode();
System.out.println("name:" + name + " code: " + code);
}
按照方法test2()的执行情况,可能会出现(name = “张三”、code = 900)的情况(错误数据)。
执行完 String name = this.so.getName();后,一个线程改变了Object_IS中so的“指向”
,从线1 变为了线2 ,此时就发生了同一个方法内,操作对象不一致的情况。test1()方法不会发生这种情况!