① suspend 与 resume 方法极易造成公共的同步对象的独占,使得其他线程无法访问公共同步对象,产生死锁
class Run {
public static void main(String[] args) {
try {
final SynchronizedObject object = new SynchronizedObject();
Thread thread1 = new Thread() {
@Override
public void run() {
object.printString();
}
};
thread1.setName("a");
thread1.start();
Thread.sleep(1000);
Thread thread2 = new Thread() {
@Override
public void run() {
System.out.println("thread2 启动了,但进入不了 printString() 方法!只打印 1 个 begin");
System.out.println("因为 printString() 方法被 a 线程锁定并且永远 suspend 暂停了");
object.printString();
}
};
thread2.start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class SynchronizedObject {
synchronized public void printString() {
System.out.println("begin");
if (Thread.currentThread().getName().equals("a")) {
System.out.println("a 线程永远 suspend 了");
Thread.currentThread().suspend();
}
System.out.println("end");
}
}
结果:
begin
a 线程永远 suspend 了
thread2 启动了,但进入不了 printString() 方法!只打印 1 个 begin
因为 printString() 方法被 a 线程锁定并且永远 suspend 暂停了
还有另外一种独占锁的情况也需要注意
class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(1000);
thread.suspend();
System.out.println("main end!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyThread extends Thread {
private long i = 0;
@Override
public void run() {
while (true) {
i++;
System.out.println(i);
}
}
}
结果:
81171
81172
...
控制台将不打印 main end,出现这样情况的原因是,程序运行到 println() 方法内部停止时,同步锁未被释放。方法 println() 源代码如下:
public void println(long x) {
synchronized (this) {
print(x);
newLine();
}
}
这导致当前 PrintStream 对象的 println() 方法一致呈“暂停”状态,并且“锁未释放”,所以 main() 方法中的代码迟迟不能打印
main 中的 out 对象和 thread 中的 out 对象是同一个,System 中的 out 对象定义是 final static 的:
public final static PrintStream out = null;
② suspend 与 resume 方法容易出现因为线程暂停而导致数据不同步的情况
class MyObject {
private String username = "1";
private String password = "11";
public void setValue(String u, String p) {
this.username = u;
if (Thread.currentThread().getName().equals("a")) {
System.out.println("停止 a 线程");
Thread.currentThread().suspend();
}
this.password = p;
}
public void printUsernamePassword() {
System.out.println(username + " " + password);
}
}
class Run {
public static void main(String[] args) throws InterruptedException {
final MyObject myobject = new MyObject();
Thread thread1 = new Thread() {
public void run() {
myobject.setValue("a", "aa");
};
};
thread1.setName("a");
thread1.start();
Thread.sleep(500);
Thread thread2 = new Thread() {
public void run() {
myobject.printUsernamePassword();
};
};
thread2.start();
}
}
结果:
停止 a 线程
a 11
出现脏读了,因为 suspend() 使得 thread1 暂停,将 CPU 让给 thread2 后,thread2 读取到的是 thread1 没写完的数据