本文共 1989 字,大约阅读时间需要 6 分钟。
package demo;/* 脏读:数据不一致的错误。 * * 在对一个对象的方法加锁的时候,需要考虑业务的整体性, * 在demo中为setUser/getUser方法同时加锁synchronized同步关键字, * 保证业务的原子性,不然会出现业务错误。 * */public class DirtyRead { private String userName = "lc"; private String password = "123"; //设置User的名、密码 public synchronized void setUser(String userName, String password){ this.userName = userName; try { Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } this.password = password; System.out.println("There set UserName : "+userName +"---password:----"+password); } //得到User信息 public synchronized void getUser(){ System.out.println("There get UserName : "+userName +"---password:----"+password); } //test public static void main(String[] args) throws InterruptedException { final DirtyRead dr1 = new DirtyRead(); Thread t1 = new Thread(new Runnable() { @Override public void run() { dr1.setUser("Jack", "123456"); } }); /* * t1线程只休眠等待1s,但是在setUser方法中,有Thread.sleep(3000);等待3秒。 * 也就是说,在set方法还没有执行完,主线程就开始调用getUser方法。 * 这样就造成了数据的不一致性,脏读 * */ t1.start(); t1.sleep(1000); dr1.getUser(); }}getUser方法没有加synchronized时:结果There get UserName : Jack---password:----123There set UserName : Jack---password:----123456getUser方法加上synchronized时:结果There set UserName : Jack---password:----123456There get UserName : Jack---password:----123456
场景描述:一个用户A在9:00访问数据库表table。查询一个数据num=100,假设table数据量1000W,需要10分钟才能查询到num,然后一个用户B , 在9:05访问数据库,对数据num进行Update,num=200。问:用户A查询到的数据num的值,是100还是200?
比如说Oracle数据库中有个Undo的概念,类似于日志,记录修改数据的旧值。A——9:00发起查询,在9:10查到num=?B在9:05提交update了num=200。A在查到num的值的时候,发现num有更改过,数据库就去Undo中找旧值返给A。就旧值返给A,即使没有,报一个异常snapshot too old的异常。数据库让它报异常都不会将num=200返回给A,这就是关系型数据库的一致性表示。
转载地址:http://pebnl.baihongyu.com/