一个synchronized跟面试官扯了半个小时

作者:微信小助手

发布时间:2020-05-16T18:10:23


前言

话说上回HashMap跟面试官扯了半个小时之后,二面迎来了没有削弱前的钟馗,法师的钩子让安琪拉有点绝望。钟馗穿着有些微微泛黄的格子道袍,站在安琪拉对面,开始发难,其中让安琪拉印象非常深刻的是法师的synchronized 钩子。

开场

面试官:  你先自我介绍一下吧!

安琪拉:  我是安琪拉,草丛三婊之一,最强中单(钟馗冷哼)!哦,不对,串场了,我是**,目前在--公司做--系统开发。

面试官:  刚才听一面的同事说你们上次聊到了synchronized,你借口说要回去补篮,现在能跟我讲讲了吧?

安琪拉: 【上来就丢钩子,都不寒暄几句,问我吃没吃】嗯嗯,是有聊到 synchronized。

面试官:  那你跟我说说为什么会需要synchronized?什么场景下使用synchronized?

安琪拉:  这个就要说到多线程访问共享资源了,当一个资源有可能被多个线程同时访问并修改的话,需要用到,还是画个图给您看一下,请看👇图:

在这里插入图片描述

安琪拉:  如上图所示,比如在王者荣耀程序中,我们队有二个线程分别统计后裔和安琪拉的经济,A线程从内存中read 当前队伍总经济加载到线程的本地栈,进行 +100 操作之后,这时候B线程也从内存中取出经济值 + 200,将200写回内存,B线程前脚刚写完,后脚A线程将100 写回到内存中,就出问题了,我们队的经济应该是300, 但是内存中存的却是100,你说糟不糟心。

面试官:  那你跟我讲讲用 synchronized 怎么解决这个问题的?

安琪拉:  在访问竞态资源时加锁,因为多个线程会修改经济值,因此经济值就是静态资源,给您show 一下吧?下图是不加锁的代码和控制台的输出,请您过目:

二个线程,A线程让队伍经济 +1 ,B线程让经济 + 2,分别执行一千次,正确的结果应该是3000,结果得到的却是 2845。

在这里插入图片描述

安琪拉:  👇这个就是加锁之后的代码和控制台的输出。

(img-6NwdhDEz-1585279691724)(/Users/zw/Library/Application Support/typora-user-images/image-20200321210555529.png)]

面试官:  我看你👆用synchronized 锁住的是代码块,synchronized 还有别的作用范围吗?

安琪拉:  嗯嗯,synchronized 有以下三种作用范围:

  1. 在静态方法上加锁;

  2. 在非静态方法上加锁;

  3. 在代码块上加锁;

    示例代码如下

    public class SynchronizedSample {

    private final Object lock = new Object();

    private static int money = 0;
    //非静态方法
    public synchronized void noStaticMethod(){
    money++;
    }
    //静态方法