亭亭画舸系春谭,直待行人酒半酣
脏读,也就是说你拿到的值不是你想要的.当然数据库中也有脏读的情况出现,那是因为事务的原因.这里不做解释.
Java线程中也会出现脏读的现象,示例代码如下:
public class ThreadTest {
public static void main(String[] args) {
try{
A a = new A();
MyThread thread = new MyThread(a);
thread.start();
Thread.sleep(1000);
a.getValue();
}catch (Exception e) {
e.printStackTrace();
}
}
}
class MyThread extends Thread{
private A a;
public MyThread(A a) {
super();
this.a = a;
}
@Override
public void run() {
super.run();
a.setValue("bb","bbb");
}
}
class A {
private String name = "aa";
private String pass = "aaa";
synchronized public void setValue(String username,String password) {
try {
this.name = username;
Thread.sleep(5000);
this.pass = password;
System.out.println("setValue Thread = " + Thread.currentThread().getName() + " name = " + name + " pass = " + pass);
}catch (Exception e) {
e.printStackTrace();
}
}
public void getValue() {
System.out.println("getValue Thread = " + Thread.currentThread().getName() + " name = " + name + " pass = " + pass);
}
}
运行结果:
这里getValue()读出来的值为name = bb,pass = aaa,这是因为线程首先调用的setValue()方法是同步的(synchronized),而getValue()方法并非同步,在设置name之后线程被睡了5秒
this.name = username;
Thread.sleep(5000);
this.pass = password;
而pass的值还没来得及设置,所以在调用getValue()方法时就会出现脏读的情况.
解决这个问题的方法当然是把getValue()方法也加上同步(synchronized):
synchronized public void getValue() {
System.out.println("getValue Thread = " + Thread.currentThread().getName() + " name = " + name + " pass = " + pass);
}
再来看运行结果:
结论:
当线程A调用了加入synchronized关键字的X方法时,其他任何线程如果调用X方法,就必须等A线程执行完才可以.因为A线程已经拿到了X方法的对象的锁.但是其他线程可以任意调用没有synchronized关键字的Y方法,但是此时可能就会出现脏读;
如果Y方法也加入了synchronized关键字,线程A先调用了X方法时,A就拿到了对象的锁,线程B如果调Y方法,就必须等待A调用完,释放锁才可以正常调用;这样也就不会出现脏读;