Java线程脏读

亭亭画舸系春谭,直待行人酒半酣
脏读,也就是说你拿到的值不是你想要的.当然数据库中也有脏读的情况出现,那是因为事务的原因.这里不做解释.
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调用完,释放锁才可以正常调用;这样也就不会出现脏读;

猜你喜欢

转载自blog.csdn.net/a_runner/article/details/80380394