synchronized 加锁 this 和 class 的区别
创始人
2025-05-31 20:28:58
0

synchronized 是 Java 语言中处理并发问题的一种常用手段,它也被我们亲切的称之为“Java 内置锁”,由此可见其地位之高。然而 synchronized 却有着多种用法,当它修饰不同对象时,其意义也是不同的,下面我们一起来看。 ​


synchronized 用法

synchronized 可以用来修饰普通方法、静态方法和代码块。 

① 修饰非静态方法

/*** synchronized 修饰普通方法*/
public synchronized void method() {// .......
} 

当 synchronized 修饰普通方法时,被修饰的方法被称为同步方法,其作用范围是整个方法

对于非静态方法,同一个实例的线程访问会被拦截,非同一实例可以同时访问。 

② 修饰静态方法

/*** synchronized 修饰静态方法*/
public static synchronized void staticMethod() {// .......
} 

当 synchronized 修饰静态的方法时,其作用的范围是整个方法

只要采用类锁,就会拦截所有线程,不论是不是同一实列,只能让一个线程访问

③ 修饰代码块

为了减少锁的粒度,我们可以选择在一个方法中的某个部分使用 synchronized 来修饰(一段代码块),从而实现对一个方法中的部分代码进行加锁,实现代码如下:

public void classMethod() throws InterruptedException {// 前置代码...// 加锁代码synchronized (SynchronizedExample.class) {// ......}// 后置代码...
} 

以上代码在执行时,被修饰的代码块称为同步语句块,其作用范围是大括号“{}”括起来的代码块,作用的对象是调用这个代码块的对象。 ​

但以上代码,除了可以加锁 class 之外,还可以加锁 this,具体示例如下:

public void classMethod() throws InterruptedException {// 前置处理代码...synchronized (this) {// ......}// 后置处理代码...
} 

那问题来了,使用 synchronized 加锁 this 和 class 的区别是什么?不都是加锁同一个类吗? ​

答案还真不是,加锁 this 和 class 区别还是很大的。下面我们通过以下 4 个示例,来看二者之间的区别。


1、加锁 class 共享一个类实例

首先,我们创建 5 个线程,调用同一个对象下 synchronized 加锁的 class 代码,具体示例如下:

import java.util.Date;
import java.util.concurrent.TimeUnit;public class SynchronizedExample {public static void main(String[] args) {// 创建当前类实例final SynchronizedExample example = new SynchronizedExample();// 创建 5 个线程执行任务for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {// 调用 synchronized 修饰的 class 方法example.classMethod();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}/*** synchronized 修饰的 class 方法* @throws InterruptedException*/public void classMethod() throws InterruptedException {synchronized (SynchronizedExample.class) {System.out.println(String.format("当前执行线程:%s,执行时间:%s",Thread.currentThread().getName(), new Date()));TimeUnit.SECONDS.sleep(1);}}
} 

以上程序的执行结果如下:

从上述结果可以看出,这 5 个线程共享的是同一把锁

2、加锁 class 创建多个实例 

接下来,我们创建 5 个线程,调用不同对象下 synchronized 加锁的 class 代码,具体示例如下:

import java.util.Date;
import java.util.concurrent.TimeUnit;public class SynchronizedExample {public static void main(String[] args) {// 创建 5 个线程执行任务for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {// 创建类实例SynchronizedExample example = new SynchronizedExample();// 调用 synchronized 修饰的 class 方法example.classMethod();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}/*** synchronized 修饰的 class 方法* @throws InterruptedException*/public void classMethod() throws InterruptedException {synchronized (SynchronizedExample.class) {System.out.println(String.format("当前执行线程:%s,执行时间:%s",Thread.currentThread().getName(), new Date()));TimeUnit.SECONDS.sleep(1);}}
} 

以上程序的执行结果如下:

 从上述结果可以看出,虽然是不同的对象,但它们使用的仍然是同一把锁

3、加锁 this 共享一个类实例

接下来,我们创建 5 个线程,调用 synchronized 加锁 this 的示例。首先我们这 5 个线程调用同一个对象的加锁方法,示例代码如下:

import java.util.Date;
import java.util.concurrent.TimeUnit;public class SynchronizedExample {public static void main(String[] args) {// 创建当前类实例final SynchronizedExample example = new SynchronizedExample();// 创建 5 个线程执行任务for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {// 调用 synchronized 修饰的 this 方法example.thisMethod();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}/*** synchronized 修饰的 this 方法* @throws InterruptedException*/public void thisMethod() throws InterruptedException {synchronized (this) {System.out.println(String.format("当前执行线程:%s,执行时间:%s",Thread.currentThread().getName(), new Date()));TimeUnit.SECONDS.sleep(1);}}
} 

以上程序的执行结果如下:

从上述结果可以看出,以上线程使用的都是同一把锁

4、加锁 this 创建多个类实例

最后一个示例最为特殊,我们使用 synchronized 加锁 this,让这 5 个线程调用各自创建对象的方法,具体示例如下:

import java.util.Date;
import java.util.concurrent.TimeUnit;public class SynchronizedExample {public static void main(String[] args) {// 创建 5 个线程执行任务for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {// 创建(多个)类实例SynchronizedExample example = new SynchronizedExample();// 调用 synchronized 修饰的 this 方法example.thisMethod();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}/*** synchronized 修饰的 this 方法* @throws InterruptedException*/public void thisMethod() throws InterruptedException {synchronized (this) {System.out.println(String.format("当前执行线程:%s,执行时间:%s",Thread.currentThread().getName(), new Date()));TimeUnit.SECONDS.sleep(1);}}
} 

 以上程序的执行结果如下:

从上述结果可以看出,当使用 synchronized 加锁 this 时,如果线程调用的不是同一个对象,那么这些线程之间使用的锁都是自己独立的锁,这个结果就和 synchronized 加锁 class 的结果完全不同了。 ​


总结 

通过以上 4 个示例我们可以得出结论,当使用 synchronized 加锁 class 时,无论共享一个对象还是创建多个对象,它们用的都是同一把锁,而使用 synchronized 加锁 this 时,只有同一个对象会使用同一把锁,不同对象之间的锁是不同的。 ​

相关内容

热门资讯

安能物流实现营收、利润、货量“... 转自:中华工商时报【本报讯】日前,中国快运龙头企业安能物流发布2025年一季度业绩报告。数据显示,公...
实现国产化!我国成功研制P波段... 转自:证券日报    据新华社记者6月8日从中国科学院高能物理研究所获悉,中国散裂中子源加速器射频团...
“卖产品”转向“创生态” 苏宁... 近年来,消费者对产品和服务的需求日益多样化和个性化。当价格不再是影响消费者决策的唯一标尺,如何让购物...
游客在桃花潭景区因停车遭围殴 ... 游客一家遭多人围殴 有一天你带着家人出游,却因为一个停车位被人暴打?这听起来像是天方夜谭,但端午节假...
国际资本抢滩港股新能源赛道 转自:证券日报    ■毛艺融    去年下半年以来,已有超20家新能源公司递交港股上市申请,国际资...
这个是谁啊,好像没有看到过呢,... 这个是谁啊,好像没有看到过呢,有谁知道?我觉得他好可爱哦,长得好像柯南哦,有谁认识他?名侦探柯南啊因...
元气少女缘结神ova一共有多少... 元气少女缘结神ova一共有多少集一共四集,就是过去篇。第一集《神,在过去的飞翔》 第二集《狐妖,坠...
总说”五岳归来不看山“,这句话... 总说”五岳归来不看山“,这句话的下一句是什么?五岳归来不看山,这句话的下一句是:黄山归来不看岳。这是...
《灵与肉》的作者是? 《灵与肉》的作者是?《灵与肉》的作者是: : 张贤亮
我叫高飞,关于高飞的自我介绍怎... 我叫高飞,关于高飞的自我介绍怎么写把你的优点跟缺点都写出来。真实一点的好。大家好,我是高飞,志高飞远...
大家帮忙听听十面埋伏这首歌,然... 大家帮忙听听十面埋伏这首歌,然后把感受写下来告诉我,谢谢!您说的是SHE的《十面埋伏》吧,我刚才特意...
智商指数多少可以算牛人? 智商指数多少可以算牛人?智商的指数能达到120以上的就可以算牛人了。一般人是达不到的。
岳云鹏的五环之歌最早是出自哪段... 岳云鹏的五环之歌最早是出自哪段相声的?谢谢~~出自《学歌曲》。出自相声《我忍不了》
《天使街23号》金月夜和苏佑惠... 《天使街23号》金月夜和苏佑惠真的到最后也没在一起吗?如题作者写得很模糊,也不知道苏佑惠最后到底选了...
中国历史魏晋到隋朝时期 中国历史魏晋到隋朝时期几乎都是百姓没饭吃,有人霸占商店
五一劳动节假期安全主题班会教案 五一劳动节假期安全主题班会教案一、教学目标1. 知识目标:了解五一劳动节的由来、意义及安全注意事项。...
幼儿保育主要学什么 幼儿保育主要学什么关于幼儿保育主要学什么如下:幼儿保育是中国中等职业教育专业。幼儿保育专业学课程有幼...
创业板后市的走向,创业板指数实...   11月22日,财联社报道称,今日创业板指数继续上行,成功站上3500点关口,权重股当代安普科技股...
礼器的器物分类 礼器的器物分类商周青铜礼器又泛称彝器。在先秦时期的汉民族礼学中,人们将世间的器物划分为祭器与养器(或...
货车找货源怎么找,有个小货车怎...   关键词:货源      行业:所有类别      适用卖家等级:1星-3钻      对于新手卖...