1.线程安全问题
1.线程安全案例:
我们在使用多线程的时候常常会遇到线程安全的问题
如图:
public class Demo11 {
static int count=0;
public static void main(String[] args) throws InterruptedException {
Thread thread1=new Thread(()->{
for (int i = 0; i <50000 ; i++) {
count++;
}
});
Thread thread2=new Thread(()->{
for (int i = 0; i <50000 ; i++) {
count++;
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
}
在这里按理来说我们两个线程同时对count进行相加答案应该是100000,但是实际上答案却是比100000小。这是因为两个线程为了同时拿到count而有冲突的原因。
2. 线程安全的概念
概念:想给出一个线程安全的确切定义是复杂的,但我们可以这样认为:
如果多线程环境下代码运行结果是符合我们预期的,即在单线程环境应该的结果,则说这个线程是线程安全的。
3.线程不安全的原因
1.线程是抢占式执行的:线程通常会优先抢占系统资源。
2.系统同时对同一个进行修改和操作:上面就是同时对count进行操作。
3.原子性:对数据的修改不是原子性的。
4.内存可见性和指令重排序:
2:线程安全的解决方案
首先我们要了解count在自增的过程:
- 1.load把数据从内村读到cpu寄存器中
- 2.add将数据+1
- 3.save将寄存器中的值保存到内存中
由于俩个线程的不同load,add,save的顺序不同就很有可能会出现问题。
1.synchronized关键字
上述操作都是非原子操作,也就是操作不是一个整体,打包成一个操作,也就是非原子操作打包成原子操作。此时我们就要用到synchronized()。也就是加锁。