博客之星:我去,你竟然还不会用 synchronized(1)

简介: 博客之星:我去,你竟然还不会用 synchronized

二哥,离你上一篇我去已经过去两周时间了,这个系列还不打算更新吗?着急着看呢。

以上是读者 Jason 发来的一条信息,不看不知道,一看真的是吓一跳,上次我去是 4 月 3 号更新的,离现在一个多月了,可不只是两周时间啊。可能我自己天天写,没觉得时间已经过去这么久了,是时候带来新的一篇“我去”了。


image.png


这次没有代码 review,是同事小王直接问我的,“青哥,能给我详细地说一说 synchronized 关键字怎么用吗?”他问的态度很谦逊,但我还是忍不住破口大骂:“我擦,小王,你丫的竟然不会用 synchronized,我当初是怎么面试你进来的!”


(我笔名是沉默王二,读者都叫二哥,但在公司不是的,同事叫我青哥,想知道我真名的,可以搜《Web全栈开发进阶之路》)


简单地说,当两个或者两个以上的线程同一时间要修改同一个可变的共享数据时,就需要一些保护措施,否则,共享数据修改后的结果大概率会超出你的预期。对于初学者来说,synchronized 关键字就是最好用的一种解决方案。


01、为什么需要保护


可能很多初学者不明白,为什么多线程环境下,可变共享变量修改后的结果会超出预期。为了解释清楚这一点,来看一个例子。


public class SynchronizedMethod {
    private int sum;
    public int getSum() {
        return sum;
    }
    public void setSum(int sum) {
        this.sum = sum;
    }
    public void calculate() {
        setSum(getSum() + 1);
    }
}



SynchronizedMethod 是一个非常简单的类,有一个私有的成员变量 sum,对应的 getter/setter,以及给 sum 加 1 的 calculate() 方法。


然后,我们来给 calculate() 方法写一个简单的测试用例。


可能一些初学者还不知道怎么快速创建测试用例,我这里就手摸手地现场教学下。


第一步,把鼠标移动到类名上,会弹出一个提示框。


image.png


第二步,点击「More actions」按钮,会弹出以下提示框。


image.png


第三步,选择「Create Test」,弹出创建测试用例的对话框。


image.png


选择最新的 JUnit5,如果项目之前没有引入 JUnit5 依赖的话,IDEA 会提醒你,点击 Fix,IDEA 会自动帮你添加,非常智能化。在对话框中勾选要创建测试用例的方法——calculate()。


点击 OK 按钮后,IDEA 会在 src 的同级目录 test 下创建一个名为 SynchronizedMethodTest 的测试类:


class SynchronizedMethodTest {

   @Test

   void calculate() {

   }

}


calculate() 方法上会有一个 @Test 的注解,表示这是一个测试方法。添加具体的代码,如下所示:


ExecutorService service = Executors.newFixedThreadPool(3);
SynchronizedMethod summation = new SynchronizedMethod();
IntStream.range(0, 1000)
        .forEach(count -> service.submit(summation::calculate));
service.awaitTermination(1000, TimeUnit.MILLISECONDS);
assertEquals(1000, summation.getSum());


1)Executors.newFixedThreadPool() 方法可以创建一个指定大小的线程池服务 ExecutorService。


2)通过 IntStream.range(0, 1000).forEach() 来执行 calculate() 方法 1000 次。


3)通过 assertEquals() 方法进行判断。


运行该测试用例,结果会是什么呢?


image.png


很不幸,失败了。预期的值为 1000,但实际的值是 976。这是因为多线程环境下,可变的共享数据没有得到保护。



相关文章
|
安全 Java 程序员
坚持写技术博客,我得到了什么?
最开始写博客的目的只是为了记录自己的学习,比如上面的这条,通过Inception V3模型实现花朵识别,用的是tensorflow框架实现了一个植物的识别,但是对于代码我理解并不够,因此我写下了自己对每行代码的注释,保存下来并发布。后来删除的原因是,我觉得这篇博客写的太没有博客的样子了。后来断断续续写了十来篇,然后就没有然后了。
|
测试技术 程序员
博客之星:我去,你竟然还不会用 synchronized(2)
博客之星:我去,你竟然还不会用 synchronized
99 0
博客之星:我去,你竟然还不会用 synchronized(2)
|
搜索推荐 Java 程序员
为何建议技术人写写博客呢?
每逢佳节倍思亲,今天是中秋佳节,也是国庆,你是在回家的路上还是已经到家了呢?还是在苦逼的加班呢!今天不谈技术,我们聊一聊技术人写博客这件事。
|
资源调度 Java 调度
谁是中国第一博客
谁是中国第一博客
935 0
|
安全 JavaScript 测试技术
|
搜索推荐 JavaScript Java
|
iOS开发 开发者 Swift
我的2016 “CSDN博客之星” 韩俊强的博客
2016年12月31日         时间如白驹过隙,转眼间2016年的尾巴快要抓不住了。总结一下这一年的自我价值和工作业绩,不知该如何下笔,因为不知道自己奋斗的是否还是年初的目标。大家都知道2016雾霾一直驱之不散,作为开发人员,这一年也是在紧迫的情景下进行的,时而被各种裁员新闻所忧虑,时而被“996”所困扰,但是我们在成长,不能被外界所困。
1131 0