多线程操作带来数据不一致情况分析,简单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;}@Overridepublic 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()方法不会发生这种情况!