您好,登錄后才能下訂單哦!
這篇“Java中的synchronized怎么用”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內(nèi)容,內(nèi)容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Java中的synchronized怎么用”文章吧。
使用 synchronized 無需手動執(zhí)行加鎖和釋放鎖的操作,我們只需要聲明 synchronized 關鍵字就可以了,JVM 層面會幫我們自動的進行加鎖和釋放鎖的操作。
synchronized 可用于修飾普通方法、靜態(tài)方法和代碼塊,接下來我們分別來看。
synchronized 修飾普通方法的用法如下:
/** * synchronized 修飾普通方法 */ public synchronized void method() { // .... }
當 synchronized 修飾普通方法時,被修飾的方法被稱為同步方法,其作用范圍是整個方法,作用的對象是調用這個方法的對象。
synchronized 修飾靜態(tài)方法和修飾普通方法類似,它的用法如下:
/** * synchronized 修飾靜態(tài)方法 */ public static synchronized void staticMethod() { // ....... }
當 synchronized 修飾靜態(tài)方法時,其作用范圍是整個程序,這個鎖對于所有調用這個鎖的對象都是互斥的。
所謂的互斥,指的是同一時間只能有一個線程能使用,其他線程只能排隊等待。
修飾普通方法 VS 修飾靜態(tài)方法
synchronized 修飾普通方法和靜態(tài)方法看似相同,但二者完全不同,對于靜態(tài)方法來說 synchronized 加鎖是全局的,也就是整個程序運行期間,所有調用這個靜態(tài)方法的對象都是互斥的,而普通方法是針對對象級別的,不同的對象對應著不同的鎖,比如以下代碼,同樣是調用兩次方法,但鎖的獲取完全不同,實現(xiàn)代碼如下:
import java.time.LocalDateTime; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class SynchronizedUsage { public static void main(String[] args) throws InterruptedException { // 創(chuàng)建線程池同時執(zhí)行任務 ExecutorService threadPool = Executors.newFixedThreadPool(10); // 執(zhí)行兩次靜態(tài)方法 threadPool.execute(() -> { staticMethod(); }); // 執(zhí)行兩次普通方法 SynchronizedUsage usage = new SynchronizedUsage(); usage.method(); SynchronizedUsage usage2 = new SynchronizedUsage(); usage2.method(); } /** * synchronized 修飾普通方法 * 本方法的執(zhí)行需要 3s(因為有 3s 的休眠時間) */ public synchronized void method() { System.out.println("普通方法執(zhí)行時間:" + LocalDateTime.now()); try { // 休眠 3s TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } * synchronized 修飾靜態(tài)方法 public static synchronized void staticMethod() { System.out.println("靜態(tài)方法執(zhí)行時間:" + LocalDateTime.now()); }
以上程序的執(zhí)行結果如下:
cdn.nlark.com/yuque/0/2022/png/92791/1643426201331-a9d1c594-1ad6-4366-8384-28ff1ffaed01.png">
從上述結果可以看出,靜態(tài)方法加鎖是全局的,針對的是所有調用者;而普通方法加鎖是對象級別的,不同的對象擁有的鎖也不同。
我們在日常開發(fā)中,最常用的是給代碼塊加鎖,而不是給方法加鎖,因為給方法加鎖,相當于給整個方法全部加鎖,這樣的話鎖的粒度就太大了,程序的執(zhí)行性能就會受到影響,所以通常情況下,我們會使用 synchronized 給代碼塊加鎖,它的實現(xiàn)語法如下:
public void classMethod() throws InterruptedException { // 前置代碼... // 加鎖代碼 synchronized (SynchronizedUsage.class) { // ...... } // 后置代碼... }
從上述代碼我們可以看出,相比于修飾方法,修飾代碼塊需要自己手動指定加鎖對象,加鎖的對象通常使用 this 或 xxx.class 這樣的形式來表示,比如以下代碼:
// 加鎖某個類 synchronized (SynchronizedUsage.class) { // ...... } // 加鎖當前類對象 synchronized (this) { // ...... }
this VS class
使用 synchronized 加鎖 this 和 xxx.class 是完全不同的,當加鎖 this 時,表示用當前的對象進行加鎖,每個對象都對應了一把鎖;而當使用 xxx.class 加鎖時,表示使用某個類(而非類實例)來加鎖,它是應用程序級別的,是全局生效的,如以下代碼所示:
import java.time.LocalDateTime; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class SynchronizedUsageBlock { public static void main(String[] args) throws InterruptedException { // 創(chuàng)建線程池同時執(zhí)行任務 ExecutorService threadPool = Executors.newFixedThreadPool(10); // 執(zhí)行兩次 synchronized(this) threadPool.execute(() -> { SynchronizedUsageBlock usage = new SynchronizedUsageBlock(); usage.thisMethod(); }); SynchronizedUsageBlock usage2 = new SynchronizedUsageBlock(); usage2.thisMethod(); // 執(zhí)行兩次 synchronized(xxx.class) SynchronizedUsageBlock usage3 = new SynchronizedUsageBlock(); usage3.classMethod(); SynchronizedUsageBlock usage4 = new SynchronizedUsageBlock(); usage4.classMethod(); } /** * synchronized(this) 加鎖 * 本方法的執(zhí)行需要 3s(因為有 3s 的休眠時間) */ public void thisMethod() { synchronized (this) { System.out.println("synchronized(this) 加鎖:" + LocalDateTime.now()); try { // 休眠 3s TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } } * synchronized(xxx.class) 加鎖 public void classMethod() { synchronized (SynchronizedUsageBlock.class) { System.out.println("synchronized(xxx.class) 加鎖:" + LocalDateTime.now()); }
以上程序的執(zhí)行結果如下:
以上就是關于“Java中的synchronized怎么用”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關的知識內(nèi)容,請關注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。