今天一起来认识认识 synchronized 这个一面试就会被提到的关键字。这一篇不会讲太多理论,主要先熟悉熟悉一下最简单的用法。只讨论一个问题:方法没用 synchronized 和用了 synchronized 有什么区别?

首先我们的理论基础是 synchronized 关键字是用在多线程并发的场景,所以接下来的测试代码都会模拟多线程并发的情况。我们直接通过代码来给大家讲讲加没加 synchronized 的区别。

1. 方法没加 synchronized 关键字

我们先写一个普通到不能再普通的代码,就是一个实例方法,在多线程并发的情况下执行同一个方法。如下所示。

public class NoSynchronizedTest {

    public static void main(String[] args) {
NoSynchronizedTest noSynchronizedTest = new NoSynchronizedTest();
for (int i = 0; i < 5; i ++) {
Thread thread = new Thread(() -> {
noSynchronizedTest.testNoSynchronizedMethod();
});
thread.start();
}
} public void testNoSynchronizedMethod() {
System.out.println("testNoSynchronizedMethod-start-" + Thread.currentThread().getName());
System.out.println("testNoSynchronizedMethod-end-" + Thread.currentThread().getName());
} }

运行结果:

我们可以发现如下结论:

  1. 在单线程中,执行顺序是有保证的,也就是每个 start 都优先于 end。
  2. 在多线程中,线程之间的 start 和 end 是没有先后顺序的,先进入方法的线程不一定先执行完方法。我们看运行结果的红色框,5 个线程只有 Thread-2 是完整的执行完方法,没有其他线程乱入的。

2. 方法加 synchronized 关键字

我们对上面的代码稍加修改,在方法上加 synchronized 修饰,并且在两种情况下执行代码。

5 个线程只有一个 synchronizedTest 对象。

public class SynchronizedTest {

    public static void main(String[] args) {
SynchronizedTest synchronizedTest = new SynchronizedTest();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(() -> {
synchronizedTest.testSynchronizedMethod();
});
thread.start();
}
} public synchronized void testSynchronizedMethod() {
System.out.println("testSynchronizedMethod-start-" + Thread.currentThread().getName());
System.out.println("testSynchronizedMethod-end-" + Thread.currentThread().getName());
}
}

运行结果:

5 个线程中,每个线程有各自的 synchronizedTest 对象。

public class SynchronizedTest {

    public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
SynchronizedTest synchronizedTest = new SynchronizedTest();
Thread thread = new Thread(() -> {
synchronizedTest.testSynchronizedMethod();
});
thread.start();
}
} public synchronized void testSynchronizedMethod() {
System.out.println("testSynchronizedMethod-start-" + Thread.currentThread().getName());
System.out.println("testSynchronizedMethod-end-" + Thread.currentThread().getName());
}
}

运行结果:

我们可以发现如下结论:

  1. 当 5 个线程中只有一个对象时,5 个线程之间的执行顺序是串行的,互不影响,线程0进入方法后,其他线程就无法再进入方法了,得等待线程0执行完后,其他线程才能进入,并且一次只能有1个线程进入。
  2. 每个线程一个对象时,就不会出现排队的场景,各个线程互不影响,相当于每个线程都有各自的资源,没有互相竞争的关系。

由此,我们可以得出什么呢?synchronized 关键字就是悲观锁的具体实现,在多线程并发竞争同一资源时,实现同一时刻只有一个线程能操作资源。

这篇文章是了解 synchronized 最最最皮毛的知识,对 synchronized 熟悉的朋友可以当做是回顾知识点,不熟悉的朋友可以当做是入门,后面会继续深挖知识点。

如果觉得这篇文章看了有收获,麻烦点个在看,支持一下,原创不易。

推荐阅读

写了那么多年 Java 代码,终于 debug 到 JVM 了

全网最新最简单的 openjdk13 代码编译

了解Java线程优先级,更要知道对应操作系统的优先级,不然会踩坑

线程最最基础的知识

老板叫你别阻塞了

吃个快餐都能学到串行、并行、并发

泡一杯茶,学一学同异步

进程知多少?

设计模式看了又忘,忘了又看?

后台回复『设计模式』可以获取《一故事一设计模式》电子书

觉得文章有用帮忙转发&点赞,多谢朋友们!

加不加 synchronized 有什么区别?的更多相关文章

  1. 类中定义成员方法。加不加public有什么区别?

    class Trangle{ double sideA, sideB, sideC, area, length; boolean flag; Trangle(double a, double b, d ...

  2. 编译程序加不加 -lpthread 的区别【转】

    转自:http://www.cnblogs.com/Swartz/articles/3939382.html 作者:Lokki 出处:http://www.cnblogs.com/Swartz/ 欢迎 ...

  3. python r r+;w w+;a a+;以及加不加b区别

    #以下内容均在正常打开文件的情况下运行 一.列表格 模式 可做操作 若文件不存在 是否覆盖 r 只能读 报错 --- r+ 可读可写 报错 是 w 只能写 创建 是 w+ 可读可写 创建 是 a 只能 ...

  4. shell脚本加不加export的区别

    加了export: jackyyu@ubuntu:~$ cat 1.sh #!/bin/dash test=test echo ${test} echo ${TERM} TERM=dumb expor ...

  5. Synchronized与ReentrantLock区别总结(简单粗暴,一目了然)

    这篇文章是关于这两个同步锁的简单总结比较,关于底层源码实现原理没有过多涉及,后面会有关于这两个同步锁的底层原理篇幅去介绍. 相似点:这两种同步方式有很多相似之处,它们都是加锁方式同步,而且都是阻塞式的 ...

  6. scanf加不加\n?

    近两天用vs2013敲代码碰到的问题 关于scanf小括号中加不加\n的区别 例程序如下所示: 第一个程序: int main(){ ; printf("你会去敲代码吗?(选择1 or 0) ...

  7. volatile和synchronized到底啥区别?多图文讲解告诉你

    你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...

  8. phpcms加载系统类与加载应用类之区别详解

    <?php 1. 加载系统类方法load_sys_class($classname, $path = ''", $initialize = 1)系统类文件所在的文件路径:/phpcms ...

  9. php的mysql语句里变量加不加单引号问题

    第一种[{$_GET['id']}加不加单引号都能正常执行没问题] $sql = "select * from `news` where `id` = {$_GET['id']}" ...

随机推荐

  1. java——构造器理解

    构造器理解 什么是构造器 构造器也叫构造方法:用于对象的初始化: 写构造器注意事项 构造器名与类名一致:有返回值但是不能定义返回类型(返回值类型是本类,可以加一个空的return): 构造器的调用 通 ...

  2. html-css:浮动_清除浮动

    1.浮动 清除浮动之前我们首先需要了解为什么要清除浮动 1. 假设我们有一个父盒子,不设置高度,其高度有内部子盒子的大小自动撑开,这样是完全可行的,因为有时候我们并不想直接固定死父盒子的大小,而是根据 ...

  3. coding++ :SQLyog 最新版本12.5-64bit 破解版

    点我下载 SQLyog 12.5-64bit 版本(包含注册码)

  4. [React]核心概念

    本文是对React文档:核心概念部分的笔记,内容大致与文档相同. 文档链接 React哲学部分写的很好,务必要看 JSX JSX是JS的语法扩展,配合react使用,为JS和HTML的混写 JSX支持 ...

  5. 电脑网络诊断显示Win10无法与设备或资源(DNS)通信解决办法

    最近是做多错多还是人有点儿衰神附体,软件,电脑系统,各种问题层出不穷,今天早上打开电脑发现不少软件都无法联网,神马百度商桥,腾讯浏览器,百度云...昨天百度商桥打不开还以为是软件出了问题,因为火狐浏览 ...

  6. [白话解析] 通俗解析集成学习之bagging,boosting & 随机森林

    [白话解析] 通俗解析集成学习之bagging,boosting & 随机森林 0x00 摘要 本文将尽量使用通俗易懂的方式,尽可能不涉及数学公式,而是从整体的思路上来看,运用感性直觉的思考来 ...

  7. springboot + aop + Lua分布式限流的最佳实践

    整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 一.什么是限流?为什么要限流? 不知道大家有没有做过帝都的地铁, ...

  8. 从上帝视角看Java如何运行

    JVM内存结构 可以看出JVM从宏观上可以分为 ‘内部’  及 ‘外部’  两个部分(便于记忆理解): ‘内部’包含:线程共享(公有)数据区 和 线程隔离(私有)数据区 ‘外部’包含:类加载子系统.垃 ...

  9. jenkins集成sonarQube实现代码质量检查

    1.sonarQube的简介 SonarQube是一款自动化代码审查工具,用于检测代码中的错误.漏洞和代码异味.它可以与你现有的工作流集成,以支持跨项目分支和拉取请求的连续代码检查. 其工作流程如下: ...

  10. Java基础知识3-类和对象(1)

    面向过程和面向对象的区别 面向过程(结构化程序设计) 实际上是一个面向操作过程,首先设计一系列过程(算法)来求解问题(操作数据),然后再考虑存储数据的方式(组织数据).即程序=算法\+数据结构.对应典 ...