在多線程編程中,線程同步是必不可少的一個概念。線程同步指的是多個線程訪問共享資源時的控制問題。Java提供了多種實現線程同步的方法,這篇文章將從多個方面對線程同步的實現方法進行詳細闡述。
一、synchronized關鍵字
Java中的synchronized關鍵字是實現線程同步的最基本的方法。synchronized關鍵字可以將方法或代碼塊標記為同步的,從而保證同一時刻只有一個線程可以訪問被保護的方法或代碼塊,避免多個線程同時對共享資源進行訪問。
public class SyncTest implements Runnable {
private synchronized void myMethod() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " print " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
myMethod();
}
public static void main(String[] args) {
SyncTest test = new SyncTest();
Thread thread1 = new Thread(test);
Thread thread2 = new Thread(test);
thread1.start();
thread2.start();
}
}
上面的例子中,myMethod方法被標記為synchronized,因此在同一時刻只有一個線程可以執行myMethod方法中的代碼塊。運行該程序可以看到兩個線程交替輸出數字。
二、使用Lock接口
Java 5引入了Lock接口,Lock接口提供了和synchronized關鍵字相同的功能,但是可以更加靈活地控制同步代碼塊的粒度。對於需要更加靈活地控制同步代碼塊的情況,可以考慮使用Lock接口。
public class LockTest implements Runnable {
private Lock lock = new ReentrantLock();
private void myMethod() {
lock.lock();
try {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " print " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
}
}
@Override
public void run() {
myMethod();
}
public static void main(String[] args) {
LockTest test = new LockTest();
Thread thread1 = new Thread(test);
Thread thread2 = new Thread(test);
thread1.start();
thread2.start();
}
}
上面的例子中,使用ReentrantLock作為鎖對象,通過調用lock方法和unlock方法進行同步。與synchronized關鍵字的方式相比,Lock接口提供了更加靈活的同步粒度控制。
三、使用wait、notify和notifyAll方法
Java中的Object類提供了wait、notify和notifyAll三個方法,這三個方法可以用於實現線程間的通信和同步。wait方法使得當前線程等待,直到其他線程調用notify或notifyAll方法喚醒它。notify方法喚醒單個正在等待的線程,而notifyAll方法喚醒所有正在等待的線程。
public class WaitNotifyTest {
private static final Object lock = new Object();
static class MyThread1 extends Thread {
@Override
public void run() {
synchronized (lock) {
System.out.println("Thread 1 is running...");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1 is resumed...");
}
}
}
static class MyThread2 extends Thread {
@Override
public void run() {
synchronized (lock) {
System.out.println("Thread 2 is running...");
lock.notify();
System.out.println("Thread 2 is completed...");
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new MyThread1();
Thread thread2 = new MyThread2();
thread1.start();
Thread.sleep(1000);
thread2.start();
}
}
上面的例子中,使用wait和notify方法實現了兩個線程之間的同步。Thread 1先獲取了lock對象的鎖,然後調用wait方法釋放鎖並等待,等待Thread 2調用lock對象的notify方法進行喚醒。Thread 2調用lock對象的notify方法喚醒了Thread 1。
四、使用Condition接口
Java 5引入了Condition接口,Condition接口是對wait、notify和notifyAll方法的升級版,可以讓線程更加精細地控制等待和通知的顆粒度。和Lock接口一樣,Condition接口可以更加靈活地控制同步代碼塊的粒度。
public class ConditionTest {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private void myMethod() throws InterruptedException {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " await...");
condition.await();
System.out.println(Thread.currentThread().getName() + " resumed...");
} finally {
lock.unlock();
}
}
public void signal() throws InterruptedException {
lock.lock();
try {
System.out.println("Signal...");
condition.signal();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ConditionTest test = new ConditionTest();
Thread thread1 = new Thread(() -> {
try {
test.myMethod();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread thread2 = new Thread(() -> {
try {
test.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread1.start();
Thread.sleep(1000);
thread2.start();
}
}
上面的例子中,使用Condition接口實現線程間的同步。myMethod方法獲取lock鎖對象並等待條件變量,通過調用condition.await方法進行等待。signal方法獲取lock鎖對象並發出喚醒信號,通過調用condition.signal方法進行喚醒。通過使用Condition接口可以更加靈活地控制同步的粒度。
五、總結
本文對Java線程同步的實現方法進行了詳細的闡述,包括synchronized關鍵字、Lock接口、wait、notify和notifyAll方法以及Condition接口。在多線程編程中,線程同步是一個非常重要的概念,合理地使用上述方法可以保證多個線程之間的正確協作。
原創文章,作者:GRSE,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/150133.html
微信掃一掃
支付寶掃一掃