1.简介
当多个线程访问一个对象时,如果不用考虑这些线程在运行环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方未进行任何其它协调操作情况下,调用这个对象的行为都可以获得正确结果,那么这个对象便是线程安全的。
2.线程安全分析
public class ThreadError implements Runnable {
private static int index = 0;
@Override
public void run() {
for (int i = 1; i <= 10000; i++) {
index++;
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread0 = new Thread(new ThreadError());
Thread thread1 = new Thread(new ThreadError());
thread0.start();
thread1.start();
thread0.join();
thread1.join();
System.out.println("index的值:" + index);
}
}
代码运行结果如下所示,按照代码执行逻辑,输出的index值应该为20000,但是实际上并不是,而是会出现了低于20000的值,这是因为发生了线程安全问题。假如线程thread0进入到for循环内,但是还没有赋值就让出了CPU执行权,线程thread1获取CPU执行权开始执行线程任务,获取的index值会和前一步thread0获取的一样,就样就会出现index漏加的情况。
index的值:15002
3.死锁
(1).简介
指多个线程竞争资源导致互相等待的僵局,如果没有外力的作用,这种现象将一直持续下去。
(2).产生条件
- 互斥:指共享资源在某一时刻只能被一个线程所占有,具有排他性。
- 不剥夺:指被线程所占有的资源不能被其它线程强行夺走,除非自己释放。
- 保持和请求:请求新资源的线程在占有一个资源的情况下,处于阻塞状态并且不释放已有的资源。
- 循坏等待链:有这样一种等待链,链上的线程所占有的资源是其它线程正在请求的资源。
(3).示例
public class DeadLock implements Runnable {
private boolean flag = true;
private Object chinese = new Object();
private Object american = new Object();
@Override
public void run() {
if (flag) {
while (true) {
synchronized (american) {
System.out.println("...if...american");
synchronized (chinese) {
System.out.println("...if...chinese");
}
}
}
} else {
while (true) {
synchronized (chinese) {
System.out.println("...else...chinese");
synchronized (american) {
System.out.println("...else...american");
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
DeadLock deadLock = new DeadLock();
Thread t0 = new Thread(deadLock);
Thread t1 = new Thread(deadLock);
t0.start();
Thread.sleep(1000);
deadLock.flag = false;
t1.start();
}
}
代码运行结果如下所示。
...if...chinese
...if...american
...if...chinese
...if...american
......
...else...chinese