跳到主要内容

Java并发编程学习二:线程安全

一、线程安全问题

在多线程并发的情况下,很容易发生线程安全问题。

《Java Concurrency In Practice》的作者 Brian Goetz 对线程安全的定义是:
当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行问题,也不需要进行额外的同步,而调用这个对象的行为都可以获得正确的结果,那这个对象便是线程安全的

如果某个对象是线程安全的,那么对于使用者而言,在使用时就不需要考虑方法间的协调问题,比如不需要考虑不能同时写入或读写不能并行的问题,也不需要考虑任何额外的同步问题,比如不需要额外自己加 synchronized 锁。

常见的线程安全问题有这几种类型:

1. 多线程同时操作一个变量导致的运行结果错误
public class WrongResult {



volatile static int i;

public static void main(String[] args) throws InterruptedException {


Runnable r = new Runnable() {


@Override
public void run() {


for (int j = 0; j < 10000; j++) {


i++;
}
}
};
Thread thread1 = new Thread(r);
thread1.start();
Thread thread2 = new Thread(r);
thread2.start();
thread1.join();
thread2.join();
System.out.println(i);
}
}

首先定义一个 int 类型的静态变量 i,然后启动两个线程,分别对变量 i 进行 10000 次 i++ 操作。理论上得到的结果应该是 20000,但实际结果却远小于理论结果,比如可能是12996,也可能是13323,每次的结果都还不一样。