Java多线程编程核心技术(第3版)
上QQ阅读APP看书,第一时间看更新

1.11.8 使用stop()释放锁导致数据结果不一致

本节将讲解使用stop()释放锁给数据造成不一致性的结果,如果出现这样的情况,程序处理的数据完全有可能遭到破坏,最终导致程序执行的流程是错误的,在此一定要注意。下面来看一个示例。

创建项目stopThrowLock,文件MyService.java代码如下:


package service;

public class MyService {

    private String username = "a";
    private String password = "aa";

    synchronized public String getUsername() {
        return username;
    }

    synchronized public String getPassword() {
        return password;
    }

    synchronized public void printString(String username, String password) {
        try {
            this.username = username;
            Thread.sleep(100000000);
            this.password = password;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

调用业务方法printString()的线程代码如下:


package extthread;

import service.MyService;

public class MyThreadA extends Thread {

    private MyService object;

    public MyThreadA(MyService object) {
        super();
        this.object = object;
    }

    @Override
    public void run() {
        object.printString("b", "bb");
    }
}

输出数据的线程代码如下:


package extthread;

import service.MyService;

public class MyThreadB extends Thread {

    private MyService object;

    public MyThreadB(MyService object) {
        super();
        this.object = object;
    }

    @Override
    public void run() {
        System.out.println(object.getUsername() + " " + object.getPassword());
        System.out.println("  end " + System.currentTimeMillis());
    }
}

文件Run.java代码如下:


package test;

import extthread.MyThreadA;
import extthread.MyThreadB;
import service.MyService;

public class Run {
    public static void main(String[] args) throws InterruptedException {
        MyService service = new MyService();
        MyThreadA myThreadA = new MyThreadA(service);
        MyThreadB myThreadB = new MyThreadB(service);
        myThreadA.start();
        Thread.sleep(500);
        myThreadB.start();
        System.out.println("begin " + System.currentTimeMillis());
        Thread.sleep(5000);
        myThreadA.stop();
    }
}

程序运行结果如图1-52所示。

图1-52 强制stop造成数据不一致

当执行stop()方法后MyThreadA才会释放锁,线程MyThreadB才能执行同步的get()方法,并且synchronized同步的getUsername()和getPassword()方法取出的是未处理完成的半成品错误数据。

由于stop()方法已经在JDK中被标为“作废/过期”的方法,显然它在功能上具有缺陷,所以不建议在程序中使用stop()方法停止线程。