脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
public class Dirtyread { private String userName="pdz"; private String password="12345"; public synchronized void updateUser(String userName, String password) { this.userName = userName; try { Thread.currentThread().sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } this.password = password; System.out.println("更新用户信息姓名为:" + userName + "密码为:" + password); } public void queryUser() { System.out.println("获取用户信息姓名:" + userName + "密码:" + password); } public static void main(String[] args) { final Dirtyread dirtyread = new Dirtyread(); Thread t1 = new Thread(new Runnable() { @Override public void run() { dirtyread.updateUser("张三", "111111"); } }); t1.start(); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } dirtyread.queryUser(); } }
上述代码中我们有一个线程t1和主线程main。为了放置更新用户数据出现冲突,所以我们把updateUser方法进行了同步。当程序运行后,结果:
获取用户信息姓名:张三密码:12345 更新用户信息姓名为:张三密码为:111111
我们获取的信息并不是完全修改后的信息。而是密码还是原来的密码,而姓名却是修改后的密码。这就是脏读。因为对象的属性帐号和密码在更新方法和获取方法之中,我们都是资源共享。也就是说多个线程在执行不同的方法的时候,都是共享这两个属性的值。所以必须要对这两个方法都进行同步。解决方法就是queryUser方法也进行synchronizedx修饰。