Java中的synchronized關鍵字
當我們在程式中啟動兩個或多個執行緒時,可能出現多個執行緒試圖訪問同一資源的情況,最終由於併發問題而產生不可預測的結果。例如,如果多個執行緒試圖寫入同一個檔案,則它們可能會損壞資料,因為其中一個執行緒可能會覆蓋資料,或者當一個執行緒正在開啟同一個檔案時,另一個執行緒可能正在關閉同一個檔案。
因此,需要同步多個執行緒的操作,並確保在給定時間點只有一個執行緒可以訪問資源。這是使用稱為**監視器**的概念實現的。Java中的每個物件都與一個監視器關聯,執行緒可以鎖定或解鎖該監視器。一次只有一個執行緒可以持有監視器的鎖。
Java程式語言提供了一種非常方便的方法來建立執行緒並使用**synchronized**塊同步其任務。您可以將共享資源保留在此塊中。以下是synchronized語句的一般形式:
語法
synchronized(objectidentifier) {
// Access shared variables and other shared resources
}這裡,**objectidentifier** 是對物件的引用,其鎖與synchronized語句表示的監視器相關聯。現在我們將看到兩個示例,我們將使用兩個不同的執行緒列印計數器。當執行緒不同步時,它們列印的計數器值不是按順序的,但是當我們將計數器放在synchronized()塊內列印時,它會為兩個執行緒按順序列印計數器。
無同步的多執行緒示例
這是一個簡單的示例,它可能按順序列印計數器值,也可能不按順序列印計數器值,並且每次執行它時,它都會根據CPU對執行緒的可用性產生不同的結果。
示例
class PrintDemo {
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
threadName = name;
PD = pd;
}
public void run() {
PD.printCount();
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}每次執行此程式都會產生不同的結果:
輸出
Starting Thread - 1 Starting Thread - 2 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 5 Counter --- 2 Counter --- 1 Counter --- 4 Thread Thread - 1 exiting. Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting.
帶同步的多執行緒示例
這是同一個示例,它按順序列印計數器值,並且每次執行它時,它都會產生相同的結果。
示例
class PrintDemo {
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
threadName = name;
PD = pd;
}
public void run() {
synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}每次執行此程式都會產生相同的結果:
輸出
Starting Thread - 1 Starting Thread - 2 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 1 exiting. Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting.
廣告
資料結構
網路
RDBMS
作業系統
Java
iOS
HTML
CSS
Android
Python
C語言程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP