溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

synchronized加鎖this和class的區(qū)別是什么

發(fā)布時(shí)間:2021-12-20 11:33:06 來源:億速云 閱讀:223 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“synchronized加鎖this和class的區(qū)別是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

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

synchronized 用法

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

① 修飾普通方法

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

當(dāng) synchronized 修飾普通方法時(shí),被修飾的方法被稱為同步方法,其作用范圍是整個(gè)方法,作用的對(duì)象是調(diào)用這個(gè)方法的對(duì)象。

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

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

當(dāng) synchronized 修飾靜態(tài)的方法時(shí),其作用的范圍是整個(gè)方法,作用對(duì)象是調(diào)用這個(gè)類的所有對(duì)象。

③ 修飾代碼塊

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

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

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

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

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

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

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

1.加鎖 class 共享一個(gè)類實(shí)例

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

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class SynchronizedExample {

    public static void main(String[] args) {
        // 創(chuàng)建當(dāng)前類實(shí)例
        final SynchronizedExample example = new SynchronizedExample();
        // 創(chuàng)建 5 個(gè)線程執(zhí)行任務(wù)
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 調(diào)用 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("當(dāng)前執(zhí)行線程:%s,執(zhí)行時(shí)間:%s",
                    Thread.currentThread().getName(), new Date()));
            TimeUnit.SECONDS.sleep(1);
        }
    }
}

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

synchronized加鎖this和class的區(qū)別是什么

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

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

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

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class SynchronizedExample {

    public static void main(String[] args) {
        // 創(chuàng)建 5 個(gè)線程執(zhí)行任務(wù)
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 創(chuàng)建類實(shí)例
                        SynchronizedExample example = new SynchronizedExample();
                        // 調(diào)用 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("當(dāng)前執(zhí)行線程:%s,執(zhí)行時(shí)間:%s",
                    Thread.currentThread().getName(), new Date()));
            TimeUnit.SECONDS.sleep(1);
        }
    }
}

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

synchronized加鎖this和class的區(qū)別是什么

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

3.加鎖 this 共享一個(gè)類實(shí)例

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

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class SynchronizedExample {

    public static void main(String[] args) {
        // 創(chuàng)建當(dāng)前類實(shí)例
        final SynchronizedExample example = new SynchronizedExample();
        // 創(chuàng)建 5 個(gè)線程執(zhí)行任務(wù)
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 調(diào)用 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("當(dāng)前執(zhí)行線程:%s,執(zhí)行時(shí)間:%s",
                    Thread.currentThread().getName(), new Date()));
            TimeUnit.SECONDS.sleep(1);
        }
    }
}

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

synchronized加鎖this和class的區(qū)別是什么

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

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

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

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class SynchronizedExample {

    public static void main(String[] args) {
        // 創(chuàng)建 5 個(gè)線程執(zhí)行任務(wù)
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 創(chuàng)建(多個(gè))類實(shí)例
                        SynchronizedExample example = new SynchronizedExample();
                        // 調(diào)用 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("當(dāng)前執(zhí)行線程:%s,執(zhí)行時(shí)間:%s",
                    Thread.currentThread().getName(), new Date()));
            TimeUnit.SECONDS.sleep(1);
        }
    }
}

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

synchronized加鎖this和class的區(qū)別是什么

從上述結(jié)果可以看出,當(dāng)使用 synchronized 加鎖 this 時(shí),如果線程調(diào)用的不是同一個(gè)對(duì)象,那么這些線程之間使用的鎖都是自己獨(dú)立的鎖,這個(gè)結(jié)果就和 synchronized 加鎖 class 的結(jié)果完全不同了。

“synchronized加鎖this和class的區(qū)別是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI