日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

synchronized 加锁 this 和 class 的区别!

發(fā)布時間:2025/3/11 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 synchronized 加锁 this 和 class 的区别! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者 | 王磊

來源 | Java中文社群(ID:javacn666)

轉載請聯(lián)系授權(微信ID:GG_Stone)

synchronized 是 Java 語言中處理并發(fā)問題的一種常用手段,它也被我們親切的稱之為“Java 內置鎖”,由此可見其地位之高。然而 synchronized 卻有著多種用法,當它修飾不同對象時,其意義也是不同的,下面我們一起來看。

synchronized 用法

synchronized 可以用來修飾普通方法、靜態(tài)方法和代碼塊

① 修飾普通方法

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

當 synchronized 修飾普通方法時,被修飾的方法被稱為同步方法,其作用范圍是整個方法,作用的對象是調用這個方法的對象。

② 修飾靜態(tài)方法

/*** synchronized 修飾靜態(tài)方法*/ public static synchronized void staticMethod() {// ....... }

當 synchronized 修飾靜態(tài)的方法時,其作用的范圍是整個方法,作用對象是調用這個類的所有對象。

③ 修飾代碼塊

為了減少鎖的粒度,我們可以選擇在一個方法中的某個部分使用 synchronized 來修飾(一段代碼塊),從而實現(xiàn)對一個方法中的部分代碼進行加鎖,實現(xiàn)代碼如下:

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

以上代碼在執(zhí)行時,被修飾的代碼塊稱為同步語句塊,其作用范圍是大括號“{}”括起來的代碼塊,作用的對象是調用這個代碼塊的對象。

但以上代碼,除了可以加鎖 class 之外,還可以加鎖 this,具體示例如下:

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

那問題來了,使用 synchronized 加鎖 this 和 class 的區(qū)別是什么?不都是加鎖同一個類嗎?

答案還真不是,加鎖 this 和 class 區(qū)別還是很大的。下面我們通過以下 4 個示例,來看二者之間的區(qū)別。

1.加鎖 class 共享一個類實例

首先,我們創(chuàng)建 5 個線程,調用同一個對象下 synchronized 加鎖的 class 代碼,具體示例如下:

import java.util.Date; import java.util.concurrent.TimeUnit;public class SynchronizedExample {public static void main(String[] args) {// 創(chuàng)建當前類實例final SynchronizedExample example = new SynchronizedExample();// 創(chuàng)建 5 個線程執(zhí)行任務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("當前執(zhí)行線程:%s,執(zhí)行時間:%s",Thread.currentThread().getName(), new Date()));TimeUnit.SECONDS.sleep(1);}} }

以上程序的執(zhí)行結果如下:

從上述結果可以看出,這 5 個線程共享的是同一把鎖。

2.加鎖 class 創(chuàng)建多個實例

接下來,我們創(chuàng)建 5 個線程,調用不同對象下 synchronized 加鎖的 class 代碼,具體示例如下:

import java.util.Date; import java.util.concurrent.TimeUnit;public class SynchronizedExample {public static void main(String[] args) {// 創(chuàng)建 5 個線程執(zhí)行任務for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {// 創(chuàng)建類實例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("當前執(zhí)行線程:%s,執(zhí)行時間:%s",Thread.currentThread().getName(), new Date()));TimeUnit.SECONDS.sleep(1);}} }

以上程序的執(zhí)行結果如下:

從上述結果可以看出,雖然是不同的對象,但它們使用的仍然是同一把鎖。

3.加鎖 this 共享一個類實例

接下來,我們創(chuàng)建 5 個線程,調用 synchronized 加鎖 this 的示例。首先我們這 5 個線程調用同一個對象的加鎖方法,示例代碼如下:

import java.util.Date; import java.util.concurrent.TimeUnit;public class SynchronizedExample {public static void main(String[] args) {// 創(chuàng)建當前類實例final SynchronizedExample example = new SynchronizedExample();// 創(chuàng)建 5 個線程執(zhí)行任務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("當前執(zhí)行線程:%s,執(zhí)行時間:%s",Thread.currentThread().getName(), new Date()));TimeUnit.SECONDS.sleep(1);}} }

以上程序的執(zhí)行結果如下:

從上述結果可以看出,以上線程使用的都是同一把鎖。

4.加鎖 this 創(chuàng)建多個類實例

最后一個示例最為特殊,我們使用 synchronized 加鎖 this,讓這 5 個線程調用各自創(chuàng)建對象的方法,具體示例如下:

import java.util.Date; import java.util.concurrent.TimeUnit;public class SynchronizedExample {public static void main(String[] args) {// 創(chuàng)建 5 個線程執(zhí)行任務for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {// 創(chuàng)建(多個)類實例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("當前執(zhí)行線程:%s,執(zhí)行時間:%s",Thread.currentThread().getName(), new Date()));TimeUnit.SECONDS.sleep(1);}} }

以上程序的執(zhí)行結果如下:



從上述結果可以看出,當使用 synchronized 加鎖 this 時,如果線程調用的不是同一個對象,那么這些線程之間使用的鎖都是自己獨立的鎖,這個結果就和 synchronized 加鎖 class 的結果完全不同了。

總結

通過以上 4 個示例我們可以得出結論,當使用 synchronized 加鎖 class 時,無論共享一個對象還是創(chuàng)建多個對象,它們用的都是同一把鎖,而使用 synchronized 加鎖 this 時,只有同一個對象會使用同一把鎖,不同對象之間的鎖是不同的

本系列原創(chuàng)文章推薦

1.線程的故事:我的3位母親成就了優(yōu)秀的我!

2.線程池的7種創(chuàng)建方式,強烈推薦你用它...

3.輕量級鎖一定比重量級鎖快嗎?

4.這樣終止線程,竟然會導致服務宕機?

5.漫畫:如何證明sleep不釋放鎖,而wait釋放鎖?

6.池化技術到達有多牛?看了線程和線程池的對比嚇我一跳!

7.求求你,別再用wait和notify了!

8.Semaphore自白:限流器用我就對了!

9.CountDownLatch:別浪,等人齊再團!

10.CyclicBarrier:人齊了,老司機就發(fā)車了!

11.Java中用戶線程和守護線程區(qū)別這么大?

12.ThreadLocal不好用?那是你沒用對!

13.ThreadLocal內存溢出代碼演示和原因分析!

14.SimpleDateFormat線程不安全的5種解決方案!

總結

以上是生活随笔為你收集整理的synchronized 加锁 this 和 class 的区别!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。