线程脏读解析

来源:互联网 发布:电脑软件怎么制作 编辑:程序博客网 时间:2024/06/06 03:22

为实现多个线程调用同一个方法时,为了避免数据出现交叉问题的情况。使用synchronized关键字来进行同步。虽然在赋值时进行了同步,但在取值时有可能出现一些意想不到的意外,这种情况就是脏读。发生脏读的情况是在读取实例变量时,此值已经被其他线程修改过了。

  一下编写相关测试类。

PublicVar.java

public class PublicVar {public String username = "A";public String password = "AA";synchronized public void setValue(String username, String password) {try {this.username = username;Thread.sleep(5000);this.password = password;System.out.println("setValue method thread name=" + Thread.currentThread().getName() +"username="+username+"password="+password);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void getValue(){System.out.println("getValue method thread name=" +Thread.currentThread().getName()+"usernme="+username+"password="+password);}}
注意其中的setValue()方法添加了关键字synchronized,而getValue()方法没有添加

创建线程类并调用PublicVar类中的setValue方法。
ThreadA.java
public class ThreadA extends Thread{private PublicVar publicVar;public ThreadA(PublicVar publicVar) {super();this.publicVar=publicVar;}@Overridepublic void run() {super.run();publicVar.setValue("B", "BB");}}
测试类

public class Test {public static void main(String[] args) {try {PublicVar publicVar = new PublicVar();ThreadA threadA = new ThreadA(publicVar);threadA.start();/* * 在PublicVar类的setValue()方法中给username赋值后让线程睡了5秒之后才给password赋值 * this.username = username; * Thread.sleep(5000); * this.password = password;如果在线程睡的这5秒中之内有其他线程访问这两个变量,就会得到username=B,password=AA * 此时让线程睡0.2秒然后执行getValue()方法,这个时候 0.2秒小于5秒。因此得到的值就是username=B,password=AA。如果此时让 * 线程睡的时间大于5秒则username=B,password=BB。这就是所谓的脏读 */Thread.sleep(200);//Thread.sleep(10000);publicVar.getValue();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

仔细看注释。
控制台打印结果:



避免出现脏读的方法就是在相应的方法前面添加关键字synchronized。如下图



原创粉丝点击