[EP2][线程基础II][多线程资源竞争和并发安全]
=======
多线程资源竞争
什么情况下会发生资源竞争?
- 单线程运行的程序不会发生资源竞争
单线程的程序 代码按顺序执行 符合人的思路不会发生资源竞争 也不会存在线程安全问题
JVM底层会进行一些,命令重排序方法内联等优化,导致代码的执行顺序可能和编写的
不一致。但是Java内存模型会保证有先后顺序关联的代码,会被正确的按顺序执行。
- 一个单线程运行的程序
public void testOneThread() {
public static void main(String[] args) {
OnePlainClazz onePlainClazz=new OnePlainClazz();
onePlainClazz.run();
}
}
public class OnePlainClazz {
public void run() {
int a=1;
int b=2;
int c=0;
for(int i=0;i<1000;i++)
{ int var=a+b;
c=var+c;
}
System.out.println(c);
}
}
运行的结果 是可知的 为3000
但是多线程时 却不是这样
多线程程序运行时 程序由系统调度
现代操作系统一般是乱序执行的
所以 在多线程时 程序执行顺序并不是
你预想中的执行顺序
- 一个多线程并发运行的程序
线程并发安全
public void testMultiThread() {
OnePlainClazz onePlainClazz=new OnePlainClazz();
Thread runer1=new Thread(){
@Override
public void run() {
onePlainClazz.runCommon();
}
};
Thread runer2=new Thread(){
@Override
public void run() {
onePlainClazz.runCommon();
}
};
Thread runer3=new Thread(){
@Override
public void run() {
onePlainClazz.runCommon();
}
};
public class OnePlainClazz {
public void run() {
private int ca=1;
private int cb=2;
private int res=0;
public void runCommon() {
for(int i=0;i<10000;i++)
{
int var=ca+cb;
res=var+res;
}
System.out.println(res);
}
}
此程序的运行结果
显然不是30000
运行一次 结果:
39750
44826
40221
这种运行结果和预期结果不一致的情况
就是多线程不安全导致的
那么怎么解决此问题呢
一个办法就是 加锁
保证每一时刻只有一个线程能访问此段代码
加锁后 同一时刻只有一个线程
能访问此段代码 那么其他线程
呢? 只能等待 等待此线程执行完
并释放锁 然后等待的线程要重新
获取锁才能执行代码段
此时 就成产生了资源竞争
线程并发安全
每个人肯定不希望自己的程序不按照预想的情况执行
而要最大程度利用硬件的性能,那么多线程是不可避免
的。所以保证多线程并发安全,让多线程程序也按照预
设执行就是程序员的责任。那么什么情况下是线程安全
的,什么情况下是线程不安全的呢?
这就需要理解Java内存模型(Java Memory Model)