脏读:再赋值时进行了同步,但是在读取值的时候有一些意想不到的意外,这种情况就是脏读。发生脏读的情况时发生在读取实例变量时,此值已经被其他线程更改过了。
示例:(代码中注释有代码执行过程)DirtyRead.java
package dirtyRead;
public class DirtyRead {
public String username="A";
public String password="AA";
synchronized public void setValue(String username,String password){
try {
this.username = username;
Thread.sleep(5000);//3
this.password = password;//6
System.out.println("setValue method thread name=" +
Thread.currentThread().getName()+" username =" + username+" password="+password);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void getValue(){//5
System.out.println("getValue method thread name=" +
Thread.currentThread().getName()+" username =" + username+" password="+password);
}
}
ThreadA.java
package dirtyRead;
public class ThreadA extends Thread{
private DirtyRead dirtyRead;
public ThreadA(DirtyRead dirtyRead){
this.dirtyRead = dirtyRead;
}
@Override
public void run(){
dirtyRead.setValue("B", "BB");//2
}
}
Run.java
package dirtyRead;
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
DirtyRead dirtyRead = new DirtyRead();
ThreadA a = new ThreadA(dirtyRead);
a.start(); //1
Thread.sleep(500);
dirtyRead.getValue();//4
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
getValue method thread name=main username =B password=AA
setValue method thread name=Thread-0 username =B password=BB
当getValue方法加上synchronized关键字时,脏读情况就解决了。
结果:
setValue method thread name=Thread-0 username =B password=BB
getValue method thread name=main username =B password=BB
结论:
当线程1调用一个对象加入synchronized的A方法时,线程2可以调用这个对象没有加入synchronized的B方法,2不需要等待1,因为B没有锁。
当线程1调用一个对象加入synchronized的A方法时,线程2不可以调用这个对象加入synchronized的B方法,2需要等待1,因为B有锁。
这就是不同线程“争抢”实例变量的结果。