加不加 synchronized 有什么区别?

今天一起来认识认识 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());
}
}
运行结果:

我们可以发现如下结论:
- 在单线程中,执行顺序是有保证的,也就是每个 start 都优先于 end。
- 在多线程中,线程之间的 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());
}
}
运行结果:

我们可以发现如下结论:
- 当 5 个线程中只有一个对象时,5 个线程之间的执行顺序是串行的,互不影响,线程0进入方法后,其他线程就无法再进入方法了,得等待线程0执行完后,其他线程才能进入,并且一次只能有1个线程进入。
- 每个线程一个对象时,就不会出现排队的场景,各个线程互不影响,相当于每个线程都有各自的资源,没有互相竞争的关系。
由此,我们可以得出什么呢?synchronized 关键字就是悲观锁的具体实现,在多线程并发竞争同一资源时,实现同一时刻只有一个线程能操作资源。
这篇文章是了解 synchronized 最最最皮毛的知识,对 synchronized 熟悉的朋友可以当做是回顾知识点,不熟悉的朋友可以当做是入门,后面会继续深挖知识点。
如果觉得这篇文章看了有收获,麻烦点个在看,支持一下,原创不易。
推荐阅读
写了那么多年 Java 代码,终于 debug 到 JVM 了
了解Java线程优先级,更要知道对应操作系统的优先级,不然会踩坑
后台回复『设计模式』可以获取《一故事一设计模式》电子书
觉得文章有用帮忙转发&点赞,多谢朋友们!

加不加 synchronized 有什么区别?的更多相关文章
- 类中定义成员方法。加不加public有什么区别?
class Trangle{ double sideA, sideB, sideC, area, length; boolean flag; Trangle(double a, double b, d ...
- 编译程序加不加 -lpthread 的区别【转】
转自:http://www.cnblogs.com/Swartz/articles/3939382.html 作者:Lokki 出处:http://www.cnblogs.com/Swartz/ 欢迎 ...
- python r r+;w w+;a a+;以及加不加b区别
#以下内容均在正常打开文件的情况下运行 一.列表格 模式 可做操作 若文件不存在 是否覆盖 r 只能读 报错 --- r+ 可读可写 报错 是 w 只能写 创建 是 w+ 可读可写 创建 是 a 只能 ...
- shell脚本加不加export的区别
加了export: jackyyu@ubuntu:~$ cat 1.sh #!/bin/dash test=test echo ${test} echo ${TERM} TERM=dumb expor ...
- Synchronized与ReentrantLock区别总结(简单粗暴,一目了然)
这篇文章是关于这两个同步锁的简单总结比较,关于底层源码实现原理没有过多涉及,后面会有关于这两个同步锁的底层原理篇幅去介绍. 相似点:这两种同步方式有很多相似之处,它们都是加锁方式同步,而且都是阻塞式的 ...
- scanf加不加\n?
近两天用vs2013敲代码碰到的问题 关于scanf小括号中加不加\n的区别 例程序如下所示: 第一个程序: int main(){ ; printf("你会去敲代码吗?(选择1 or 0) ...
- volatile和synchronized到底啥区别?多图文讲解告诉你
你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...
- phpcms加载系统类与加载应用类之区别详解
<?php 1. 加载系统类方法load_sys_class($classname, $path = ''", $initialize = 1)系统类文件所在的文件路径:/phpcms ...
- php的mysql语句里变量加不加单引号问题
第一种[{$_GET['id']}加不加单引号都能正常执行没问题] $sql = "select * from `news` where `id` = {$_GET['id']}" ...
随机推荐
- TensorBoard中HISTOGRAMS和DISTRIBUTIONS图形的含义
前言 之前我都是用TensorBoard记录训练过程中的Loss.mAP等标量,很容易就知道TensorBoard里的SCALARS(标量)(其中横纵轴的含义.Smoothing等). 最近在尝试模型 ...
- coding++:java—提取Html文本字符串中的内容
package com.tree.ztree_demo; import java.util.regex.Matcher; import java.util.regex.Pattern; public ...
- C 最大公约数&最小公倍数
1.最大公约数 链接 如果有一个自然数a能被自然数b整除,则称a为b的倍数,b为a的约数.几个自然数公有的约数,叫做这几个自然数的公约数.公约数中最大的一个公约数,称为这几个自然数的最大公约数. 1 ...
- yum-程序包管理器前端工具
一.要想使用yum先要指定yum源 /etc/yum.com /etc/yum.repos.d/*repo 一.yum的使用 yum [option] command 包名 option -y: c ...
- C 电压
时间限制 : 10000 MS 空间限制 : - KB 评测说明 : 1s,256m 问题描述 JOI社的某个实验室中有着复杂的电路.电路由n个节点和m根细长的电阻组成.节点被标号为1~N ...
- Failed to introspect Class [XXX] from ClassLoader [ParallelWebap报错
今天写了一个Controller,结果刚刚本地跑就给了一个惊喜 org.springframework.beans.factory.BeanCreationException: Error creat ...
- 201771010108韩腊梅《面向对象程序设计(java)》第一周学习总结
第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.com 木子林 程序设计评测:https://pintia.cn/ 19362039991@q ...
- flex布局取消子元素(img、div等)缩放:
取消子元素(img.div等)缩放: 父元素: display: flex ; 子元素: flex-shrink: 0;
- FileReader与URL.createObjectURL实现图片、视频上传前预览
之前做图片.视频上传预览常用的方案是先把文件上传到服务器,等服务器返回文件的地址后,再把该地址字符串赋给img或video的src属性,这才实现所谓的文件预览.实际上这只是文件“上传后再预览”,这既浪 ...
- ajax前端传递对象给后端
前端操作如下即可: