多个线程访问共享变量,会导致线程安全问题,导致共享变量值被非预期改变。
那么什么情况会导致共享变量存在呢?
1、类的静态变量
2、多个线程,单个Runable实例,其内部全局变量是共享的
本文主要说明Runnable多实例和单实例(即:上述第2点)的区别及可能产生的问题,详细见代码及注释。
import java.util.concurrent.TimeUnit;
/**
*
*/
public class GlobalVariableTest {
public GlobalVariableTest() {
}
class Task implements Runnable {
private int idx;
private String taskId;
public Task(String taskId) {
this.taskId = taskId;
}
public void run() {
while (true) {
try {
TimeUnit.MILLISECONDS.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +" "+ (++idx) + this.taskId);
}
}
}
public void test() {
// 多个线程,多个Runnable实例,各自独立,没有线程安全问题(除了内部静态变量访问)
// new Thread(new Task("task1")).start();
// new Thread(new Task("task2")).start();
// new Thread(new Task("task3")).start();
// new Thread(new Task("task4")).start();
// 多个线程,单个Runnable实例,变量共享,存在线程安全问题
Task task = new Task("task");
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
public static void main(String[] args) {
new GlobalVariableTest().test();
}
}
最后说明,避免线程安全问题的方法:
1、使用多实例多线程;
2、对于共享变量的操作加锁;
3、使用ThreadLocal存放线程变量,代替Runnable全局共享变量;