如何在Java中使用同步 -Manusha
在本文中,您將學習為什麼我們需要Java同步,如何編寫同步的程式碼以及有關同步的更重要的要點。
為什麼要使用同步?
如果您的程式碼在多執行緒環境中執行,則需要同步在多個執行緒之間共享的物件。否則,可能會發生兩種型別的錯誤。
- 執行緒干擾錯誤
- 記憶體一致性錯誤
Java中的執行緒干擾是一種情況,當多個同時執行的執行緒可以訪問同一資料時,就會發生這種情況。當執行緒對同一資料執行不同的操作時,這些操作可能會重疊並在記憶體中建立不一致的資料。發生這種情況時,資料可能會丟失,損壞或顯示意外行為。
在多執行緒中,一個執行緒所做的更改可能對其他執行緒不可見,並且它們對同一共享資料的檢視不一致。這稱為記憶體一致性錯誤。
因此,我們在程式碼中使用了同步,以避免因這些錯誤而頭痛。您不需要或使用同步共享,如果物件是不可變的,如果所有的執行緒只能執行只讀操作。現在,讓我們看看如何同步我們的Java程式碼。
方法同步
您可以使用synchronized關鍵字在Java中宣告一個同步方法。當執行緒呼叫同步方法時,它會在共享資料時自動鎖定物件,並線上程完成其任務時釋放該物件。因此,如果一個執行緒執行同步方法,則在同一物件上呼叫同步方法的所有其他執行緒將必須等待,直到第一個執行緒完成。讓我們來看一個例子。
class Apple { synchronized public void getApple() { for (int i = 0; i < 3; i++) { System.out.println(i); try { Thread.sleep(400); } catch (Exception e) { System.out.println(e); } } } } class Tree extends Thread { Apple apple; Tree (Apple apple) { this.apple = apple; } @Override public void run() { apple.getApple(); } } public class SyncEx1 { public static void main(String[] args) { Apple obj = new Apple(); //Object of Apple class that is shared amoung threads Tree tree1 = new Tree(obj); Tree tree2 = new Tree(obj); tree1.start(); tree2.start(); } } |
getApple()方法在示例中是同步的,一次僅允許一個執行緒訪問該方法。因此,該變數的值i將不會不一致。但是,如果我們只想同步一段程式碼而不是整個方法,該怎麼辦?那就是我們需要塊同步的時候。
塊同步
假設您的方法中有50行程式碼,但是您只想同步5行。同步塊允許您同步方法的任何特定部分。它告訴JVM一次僅允許一個執行緒訪問指定的程式碼段。
類的synchronizedList()方法java.util.Collections用於返回由指定列表支援的同步列表。因此,每當Iterator使用進行迭代同步列表時,Iterator需要同步使用需求的程式碼塊。讓我們看一下示例程式碼。
import java.util.*; public class SyncEx2{ public static void main(String []args){ try{ List<String> al = new ArrayList<>(); List movieList = Collections.synchronizedList(al); movieList.add("StarWars"); movieList.add("Avengers"); movieList.add("Inception"); synchronized(movieList) { // Synchronized block Iterator i = movieList.iterator(); while (i.hasNext()) System.out.println(i.next()); // Print Synchronized movie list } } catch (IllegalArgumentException e) { System.out.println("Exception thrown : " + e); } } } |
有關同步的重要說明
- 如果同步靜態方法,則鎖將位於類上,而不是物件上。因此,無論它有多少物件例項,在這個類靜態同步方法中都只能執行一個執行緒。
- 在同步方法或塊中可以使用3種執行緒間通訊方法。這些都是wait(),notify()和notifyAll()。
- 您可以使用該wait()方法將當前執行緒設定為釋放鎖定,然後等待另一個執行緒呼叫該物件的一個notify()或多個notifyAll()方法,或者直到指定的時間過去。
- notify()方法將選擇並喚醒在此物件上等待的單個執行緒,並且該notifyAll()方法將喚醒在該物件的監視器上等待的所有執行緒。
- 同步有很多限制,它不允許併發訪問,可能會導致死鎖,並且同步方法的執行速度非常慢。
- Java java.util.concurrent在Java 5中引入了該軟體包,它可以用作這些問題的解決方案。該軟體包提供了一組類,這些類使開發多執行緒Java應用程式更加容易。
相關文章
- 如何在Java中使用泛型 -ManushaJava泛型
- 如何在Java中實現非同步任務排程?Java非同步
- 如何在PR中同步音訊和視訊音訊
- 如何在 Java 中使用 MQTTJavaMQQT
- 如何在Ubuntu上使用FreeFileSync同步檔案Ubuntu
- PR使用教程:如何在PremierePro中調節影片影像和聲音不同步?REM
- 如何在java中呼叫js方法JavaJS
- 如何在Java中使用Deque? - Java67Java
- 如何在Java中做基準測試?JMH使用初體驗Java
- NodeJS: 如何在 Express 中處理非同步錯誤NodeJSExpress非同步
- 如何在JAVA中通^OLEDBB接ACCESS?Java
- Java中的執行緒同步Java執行緒
- 如何在java類中呼叫websphere中的jndi物件JavaWeb物件
- 如何在 PyQt 中實現非同步資料庫請求QT非同步資料庫
- 如何在Java中判斷是否為空Java
- 如何在 Java 中實現無向圖Java
- 如何在 Java 中進行圖片剪裁Java
- Java中AsynchronousFileChannel不是真正的非同步Java非同步
- Java使用讀寫鎖替代同步鎖Java
- Java同步塊(synchronized block)使用詳解JavasynchronizedBloC
- 為何在查詢中索引未被使用索引
- 教你如何在 Ubuntu 中安裝 Oracle Java 13UbuntuOracleJava
- 如何在Java中將double轉換為int?Java
- 如何在Java中反轉單連結串列?Java
- 如何在Java中將字串轉換為日期Java字串
- Java中的執行緒同步詳解Java執行緒
- 從同步原語看非阻塞同步以及Java中的應用Java
- 如何解讀 Java IO、NIO 中的同步阻塞與同步非阻塞?Java
- Promise-在Java中以同步的方式非同步程式設計PromiseJava非同步程式設計
- [轉]關於java中的 sychronized 同步方法 與 同步塊的理解JavaZed
- java同步與非同步Java非同步
- [轉載] Java中如何在方法中return返回多個值Java
- 如何在Windows 11系統中將任意檔案(如bat/log等)固定在開始選單?WindowsBAT
- 如何在 JavaScript 中更好地使用陣列JavaScript陣列
- 如何在 Blazor WebAssembly中 使用 功能開關BlazorWeb
- 如何在 Rails 中搭配 Turbolinks 使用 VueAIVue
- 同步容器(如Vector)並不是所有操作都執行緒安全!~執行緒
- 如何在Java 8中將List轉換為Map?Java