在多線程編程中,線程同步是必不可少的一個概念。線程同步指的是多個線程訪問共享資源時的控制問題。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