- 对于对象的同步和异步的方法,我们在设计自己的程序的时候,一定要考虑问题的整体性,不然就会出现数据不一致的错误,很经典的错误就是脏读(dirtyread)
- 程序实例:
-
public class DirtyRead { private String username = "z3"; private String password = "123"; public synchronized void setValue(String username, String password) { this.username = username; try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } this.password = password; System.out.println("setValue最终结果: username=" + username + ",password=" + password); } public void getValue() { System.out.println("getValue方法结果: username=" + this.username + ",password=" + password); } public static void main(String[] args) { final DirtyRead dr = new DirtyRead(); new Thread(new Runnable() { public void run() { dr.setValue("w5", "456"); } }).start(); dr.getValue(); } }
运行结果:
-
getValue方法结果: username=z3,password=123
-
setValue最终结果: username=w5,password=456
-
结果分析:我们在通过setValue方法中设置的值,结果取出来的不是我们设置的值,说明了数据脏读,主线程和子线程在数据操作时不是业务原子性的。
-
-
当我们给getValue()方法加上synchronized后,此时两个方法用的是同一把锁!
-
public class DirtyRead { private String username = "z3"; private String password = "123"; public synchronized void setValue(String username, String password) { this.username = username; try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } this.password = password; System.out.println("setValue最终结果: username=" + username + ",password=" + password); } public synchronized void getValue() { System.out.println("getValue方法结果: username=" + this.username + ",password=" + password); } public static void main(String[] args) { final DirtyRead dr = new DirtyRead(); new Thread(new Runnable() { public void run() { dr.setValue("w5", "456"); } }).start(); dr.getValue(); } }
运行结果:
setValue最终结果: username=w5,password=456
getValue方法结果: username=w5,password=456