多线程为什么会出现数据安全问题,多线程会带来哪些麻烦,应该怎么解决?
个人理解,对于单核CPU,CPU是在线程间随机快速的切换,快到就相当于同时处理多件事。而开启多个线程后,线程就会执行。一般认为,只有当线程sleep, 或者阻塞时才会停。等着条件到了被再次唤醒。
出现问题:
/**
* Created by qiaorenjie on 2018/4/5.
*/
public class Test3 {
static int a ;
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
a++; // 相当于 a= a+1;
System.out.println(Thread.currentThread().getName()+"的值: "+a);
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
a++;
System.out.println(Thread.currentThread().getName()+"的值: "+a);
}
}
});
thread2.start();
System.out.println("最后的a为: "+a);
}
}
======console=====
Thread-0的值: 77
Thread-0的值: 79
Thread-1的值: 79
Thread-0的值: 80
两条线程打印出了相同的数据79,可能是因为:每一个线程都是先去拿a,并加1.再放到一个变量中。这个动作是有可能同时发生,即产生脏读取。 两个人读到同一个值。
在a++中,相当于a = a+1(此行还是a的值),可能出现a+1;算好值后还没来得及赋值给a,即a还是原来的旧值的时候另一条线程就读了a的值,而此时a的值是旧值,不是应该更改后的新值,此时就发生了脏读,出现上面的问题。
个人看法:对于共享变量进行原子操作可以不用考虑线程安全,但是一般操作都比较复杂不可能都是原子操作的,所以怎么对同一变量进行安全的线程操作是多线程关注的重点。(本例可以通过将方法抽离出来再对方法加上锁解决)