1、线程安全的概念
如果多线程环境下代码运行的结果是符合我们预期的,即在单线程环境应该的结果,则说这个程序是线程安全的。相对来说,线程不安全就是多线程执行中,程序的执行结果和预期不相符。
线程不安全举例:num再先加100000次后减100000次后多线程预期的结果应该为0,但是结果与预期不符:
代码:
package thread.thread_0427;
/**
* Created with IntelliJ IDEA.
* Description:
* User: HuYu
* Date: 2021-05-04
* Time: 15:25
*/
public class ThreadDemo26 {
static class Counter{
//定义的一个私有的变量
private int num = 0;
//任务执行的次数
private final int maxSize = 100000;
//num++
public void incrment(){
for (int i = 0; i <maxSize ; i++) {
num++;
}
}
//num--;
public void decrment(){
for( int i = 0; i <maxSize ; i++) {
num--;
}
}
public int getNum(){
return num;
}
}
public static void main(String[] args) {
ThreadDemo25.Counter counter = new ThreadDemo25.Counter();
Thread t1 = new Thread(()->{
counter.incrment();
});
t1.start();
Thread t2 = new Thread(()->{
counter.decrment();
});
t2.start();
System.out.println("最终结果:"+counter.getNum());
}
}
结果:
这种情况电脑中线程的运行过程是并行执行,如图:
预期结果是0,但是结果为-1;
2、出现线程不安全的原因:
1、cpu抢占执行(关键因素)
2、非原子性(原子性:一部分完全执行成功/执行失败)
3、编译器优化(代码优化):编译器优化在单线程下没问题,可以提升程序的执行效率,但是在多线程下就会出现混乱,从而导致线程不安全。
4、内存不可见性问题:(多线程:在其中的一个进程的缓存区中修改了另外一个进程看不到)
代码示例:本应该设置为true要打印执行终止:
package thread.thread_0427;
/**
* Created with IntelliJ IDEA.
* Description:
* User: HuYu
* Date: 2021-05-04
* Time: 17:01
*/
public class ThreadDemo27 {
private static boolean flag = false;
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
while (!flag){
}
System.out.println("终止执行");
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("设置flag为true");
flag = true;
}
});
t2.start();
}
}
结果:
出现此情况的原因:在其中的一个进程的缓存区中修改了另外一个进程看不到,如图:
5、多个线程修改了同一个变量:
代码示例;若不是修改同一个变量那么不影响:
package thread.thread_0427;
/**
* Created with IntelliJ IDEA.
* Description:
* User: HuYu
* Date: 2021-05-04
* Time: 17:23
*/
public class ThreadDemo28 {
static class Counter{
//定义的一个私有的变量
//private int num = 0;
//任务执行的次数
private final int maxSize = 100000;
//num++
public int incrment(){
int num1 = 0;
for (int i = 0; i <maxSize ; i++) {
num1++;
}
return num1;
}
//num--;
public int decrment(){
int num2 = 0;
for( int i = 0; i <maxSize ; i++) {
num2--;
}
return num2;
}
}
private static int num1 = 0;
private static int num2 = 0;
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(()->{
num1 = counter.incrment();
});
t1.start();
Thread t2 = new Thread(()->{
num2= counter.decrment();
});
t2.start();
t1.join();
t2.join();
System.out.println("最终结果:"+(num1+num2));
}
}
结果: