本篇文章為大家帶來了關於java的相關知識,其中主要介紹了關於synchronized關鍵字的相關問題,包括了使用同步方法、使用同步語句或區塊以及什麼是同步、為什麼需要同步的相關內容,下面一起來看一下,希望對大家有幫助。
推薦學習:《java影片教學》
在平時開發中,synchronized關鍵字常遇到,你知道synchronized怎麼用嗎?本文跟大家介紹一下。
我們有兩種方法可以使用同步:
- 使用同步方法
- 使用同步語句或區塊
使用同步方法
要讓方法同步,只需將synchronized關鍵字新增至其聲明:
public class SynchronizedDemo { private int i = 0; public synchronized void add() { i++; } public synchronized void del() { i--; } public synchronized int getValue() { return i; } }
如上程式碼顯示,一共有三個同步方法:
- add()
- del()
- getValue()
每個方法同一個物件同一時刻只會被調用一次,例如一個執行緒在呼叫add()時,其他執行緒都會被阻塞,直到第一個執行緒處理完add()方法。
使用同步語句或區塊
public void del(int value){ synchronized(this){ this.i -= value; } }
如上程式碼,synchronized加在了一個{}程式碼前,這個就代表是一個同步程式碼區塊。
以上就是synchronized關鍵字兩種使用方法,以下我們來簡單的介紹一下同步相關的概念。
什麼是同步?
同步是一個控制多個執行緒存取任何共享資源的進程,可以避免不一致的結果。使用同步的主要目的是避免執行緒的不一致行為,防止執行緒幹擾。
在java中可以使用synchronized 關鍵字來實現同步的效果,synchronized只能應用於方法和區塊,不能應用於變數和類別。
為啥需要同步?
首先我們來看一段程式碼:
public class SynchronizedDemo { int i; public void increment() { i++; } public static void main(String[] args) { SynchronizedDemo synchronizedDemo = new SynchronizedDemo(); synchronizedDemo.increment(); System.out.println("计算值为:" + synchronizedDemo.i); } }
每當呼叫increment()方法時計算值都會加1:
調用2次就會加2,呼叫3次就會加3,呼叫4次就會加4:
public class SynchronizedDemo { int i; public void increment() { i++; } public static void main(String[] args) { SynchronizedDemo synchronizedDemo = new SynchronizedDemo(); synchronizedDemo.increment(); synchronizedDemo.increment(); synchronizedDemo.increment(); synchronizedDemo.increment(); System.out.println("计算值为:" + synchronizedDemo.i); } }
現在我們擴充一下上面的例子,建立一個線程去呼叫10次increment()方法:
public class SynchronizedDemo { int i; public void increment() { i++; } public static void main(String[] args) { SynchronizedDemo synchronizedDemo = new SynchronizedDemo(); Thread thread = new Thread(() -> { for (int i = 1; i <= 10; i++) { synchronizedDemo.increment(); } }); thread.start(); try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("计算值为:" + synchronizedDemo.i); } }
此時計算的結果正如我們預期的那樣,結果為10.
public class SynchronizedDemo { int i; public void increment() { i++; } public static void main(String[] args) { SynchronizedDemo synchronizedDemo = new SynchronizedDemo(); Thread thread1 = new Thread(() -> { for (int i = 1; i <= 1000; i++) { synchronizedDemo.increment(); } }); Thread thread2 = new Thread(() -> { for (int i = 1; i <= 1000; i++) { synchronizedDemo.increment(); } }); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("计算值为:" + synchronizedDemo.i); } }如上程式碼,我們建立了兩個執行緒thread1 和thread2,每個執行緒呼叫1000次increment(),理論上最終列印的值應該是
2000#,因為thread1呼叫increment ()1000次後值會變成1000,thread2呼叫increment()1000次後值會變成2000.
我們執行一下,看看結果:
public class SynchronizedDemo { int i; public synchronized void increment() { i++; } public static void main(String[] args) { SynchronizedDemo synchronizedDemo = new SynchronizedDemo(); Thread thread1 = new Thread(() -> { for (int i = 1; i <= 1000; i++) { synchronizedDemo.increment(); } }); Thread thread2 = new Thread(() -> { for (int i = 1; i <= 1000; i++) { synchronizedDemo.increment(); } }); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("计算值为:" + synchronizedDemo.i); } }這個時候我們再執行一下:
public class SynchronizedDemo { int i; public synchronized void increment() { i++; } public static void main(String[] args) { SynchronizedDemo synchronizedDemo = new SynchronizedDemo(); Thread thread1 = new Thread(() -> { for (int i = 1; i <= 10000; i++) { synchronizedDemo.increment(); } }); Thread thread2 = new Thread(() -> { for (int i = 1; i <= 10000; i++) { synchronizedDemo.increment(); } }); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("计算值为:" + synchronizedDemo.i); } }###執行結果為:###############可以看出,一個小小的synchronized竟然那麼簡單的就解決了這個問題。 ###
這個背後的原理就是線程1執行increment()方法時,因為有synchronized,所以會自動將此方法加鎖,而此時只有線程1擁有這把鎖,其他線程只能等待,直到線程1釋放這把鎖,線程2才能參與呼叫。
同理,當線程2去調用increment()時,線程2拿到鎖,線程1進入等待,直到線程2釋放鎖,就這樣,直到計算完畢,在此過程中,不會出現計算錯誤的情況。
總結
- synchronized 關鍵字是使區塊或方法同步的唯一方法。
- synchronized 關鍵字提供了鎖定的特性,它確保執行緒之間不會出現競爭條件。被鎖定後,執行緒只能從主記憶體讀取數據,讀取資料後,它會刷新寫入操作,然後才能釋放鎖定。
- synchronized 關鍵字也有助於避免程式語句的重新排序。
推薦學習:《java影片教學》
以上是一個例子看懂Java中synchronized關鍵字到底怎麼用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

WebStorm Mac版
好用的JavaScript開發工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器