前言
接上一篇内容.......
产生线程不安全的原因~
5.指令重排序~(也是和编译器优化相关)
编译器会自动调整执行指令的顺序,以达到提高效率的效果
调整的前提是,保证指令的最终效果是不变的(如果当前的逻辑只是在单线程下运行.编译器判定顺序是否影响结果,就很容易.如果当前的逻辑可能在多线程下运行.编译器判定顺序是否影响结果.就可能出错)
(编译器优化,是一个非常智能的东西,哪怕程序猿代码写的很挫.但是编译器咔咔一顿优化,代码效率还是会挺高的)
如何解决线程不安全问题~
最普适的办法,就是通过"原子性"这样的切入点来解决问题
把一些不是原子性的操作变成原子性的操作
synchronized 英文原义"同步"
这里理解为"互斥"更合适
这个单词一定要会拼写,会念
这里我们继续来看之前用到的一个案例:两个线程分别针对count自增5w次
public class TestDome7 { static class Counter{ public int count = 0; synchronized public void increase(){ count++; } } public static void main(String[] args) throws InterruptedException { Counter counter = new Counter(); Thread t = new Thread(){ @Override public void run() { for (int i = 0; i < 50000; i++) { counter.increase(); } } }; Thread t2 = new Thread(){ @Override public void run() { for (int i = 0; i < 50000; i++) { counter.increase(); } } }; t.start(); t2.start(); t.join(); t2.join(); System.out.println(counter.count); } }
如果两个线程同时并发的方式调用这个synchronized修饰的方法
此时一个线程会先执行这个方法,另外一个线程会等待,等到第一个线程方法执行完了之后,第二个线程才会继续执行
就相当于"加锁"和"解锁"
进入synchronized修饰的方法,就相当于加锁
出了synchronized修饰的方法,就相当于解锁
如果当前是已经加锁的状态,其他的线程就无法执行这里的逻辑,就只能阻塞等待
synchronized的功能本质上就是把"并发"变成"串行"
适当的牺牲一下速度,但是换来的是结果更加准确
多次打印结果: