多线程遇到问题(四)
- 竞态条件
- 竞争数据
- 缓存问题
竞态条件
当计算机正确性取决于相对时间或者调度器所控制的线程交叉时,就会产生竞态条件。
check-then-act
if(a==10){
rerurn a/2;
}
如果线程1在执行a==10后,同时线程2修改a值,最终结果就可能与想要结果不一致
read-Modify-Write
public integer getId(){
count++;
return count;
}
count++;实际执行3步操作,获取值 、++、 赋值count
count=1,线程1进入获取count ,同时线程2 获取count 然后++ 值位2,然后由于1线程以获取count 结果最后结果为2;
竞争数据
两条或者两条以上线程并发访问某一内存区域,并且有一跳线程执行写操作,并且线程没有协调好对内存访问导致。
private static Class classA;
public staatic ClassA getInstance(){
if(null==classA){
classA = new ClassA;
}
return class;
}
两个线程访问 如果1线程判断为空 创建ClassA,同时2线程可能会出现2中,1.检测到不为null直接返回,2.为null创建新.由于没有对内存访问先后导致数据竞争。
缓存问题
为性能,编译JVM以及操作系统会协调在寄存器或处理器缓存中缓存变量,而不依赖主存。
public static int a =10;
public static void main(String[] args) {
// checkThenAct();
// readModifyWrite();
Runnable r = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
a=a+100;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(r);
thread.start();
// try {
// thread.join();
// } catch (InterruptedException e) {
// }
System.out.println(a);
}
如果不放开t.join(),a取值一直缓存。
同步
保证两个或者多个线程不会同时执行同一块临界资源,临界资源一串行访问的一段代码块
同步属性:互斥与可见性
synchronized 与 volatile区别
volatile解决 可见性问题,synchronized解决互斥与可见性