一、Atomic原子類
在並發編程中,我們常常需要對共享變數進行加鎖以保證線程安全。在JDK 1.5版本中,引入了Atomic原子類,可以以一種線程安全的方式訪問單個變數。其中最常用的類就是AtomicInteger,使用方式如下:
import java.util.concurrent.atomic.AtomicInteger; public class AtomicExample { private static AtomicInteger count = new AtomicInteger(0); public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { public void run() { int newVal = count.incrementAndGet(); System.out.println("Thread 1: " + newVal); } }); Thread t2 = new Thread(new Runnable() { public void run() { int newVal = count.incrementAndGet(); System.out.println("Thread 2: " + newVal); } }); t1.start(); t2.start(); } }
上述示例中,我們使用AtomicInteger來保證了count變數的線程安全性。在多線程場景下,我們可以使用incrementAndGet()方法來保證count的原子性加1。
二、Synchronized同步鎖
在Java開發中,Synchronized是一種常用的同步機制。它可以在多線程環境下保證對共享資源的互斥訪問。在使用Synchronized時,需要注意以下幾點:
1、Synchronized可以作用於方法、代碼塊
public synchronized void testMethod() { // 方法內部代碼 } public void testMethod() { synchronized (this) { // 代碼塊 } }
2、Synchronized的鎖是對象鎖
在使用Synchronized時,我們需要明確哪個對象是鎖,只有獲取到鎖的線程才能進入同步塊進行訪問。示例代碼如下:
public class SynchronizedExample { private Object object = new Object(); private int count = 0; public void addCount() { synchronized (object) { count++; } } public int getCount() { synchronized (object) { return count; } } // 省略其他方法 }
上述示例中,我們使用object對象作為鎖,保證了count變數的線程安全性。
三、Semaphore信號量
Semaphore是一種計數信號量,用於控制訪問資源的線程數量。它可以用來保護一個有限的資源,如線程池、IO流等。在Semaphore中,我們需要先定義信號量數量,然後在需要訪問資源的線程中獲取信號量,訪問完畢後再釋放信號量。示例代碼如下:
import java.util.concurrent.Semaphore; public class SemaphoreExample { private Semaphore semaphore = new Semaphore(2); public void executeTask() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "獲取了信號量,開始執行任務"); Thread.sleep((long) (Math.random() * 5000)); System.out.println(Thread.currentThread().getName() + "執行任務完成,釋放信號量"); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } } // 省略其他方法 }
上述示例中,我們定義了一個Semaphore對象,使用它來保證並發線程不超過2個。在executeTask()方法中,我們通過semaphore.acquire()獲取信號量,執行完畢後再通過semaphore.release()釋放信號量。
四、CountDownLatch倒計時器
CountDownLatch是一種同步機制,它可以讓線程等待其他線程完成操作後再繼續執行。CountDownLatch的工作原理是通過一個計數器來實現的,計數器的初始值為線程的數量,每當一個線程完成操作後,計數器的值就減1,當計數器的值減到0時,所有等待的線程將繼續執行。示例代碼如下:
import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { private CountDownLatch countDownLatch = new CountDownLatch(3); public void doTask() { try { System.out.println(Thread.currentThread().getName() + "開始執行任務"); Thread.sleep((long) (Math.random() * 5000)); System.out.println(Thread.currentThread().getName() + "執行任務完成"); } catch (InterruptedException e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } } public void waitTaskDone() { try { countDownLatch.await(); System.out.println("所有任務執行完成!"); } catch (InterruptedException e) { e.printStackTrace(); } } // 省略其他方法 }
上述示例中,我們定義了一個CountDownLatch對象,初始計數器值為3。在doTask()方法中,執行任務完成後,通過countDownLatch.countDown()來減少計數器的值。在waitTaskDone()方法中,通過countDownLatch.await()來等待所有線程完成操作。
五、ReentrantLock可重入鎖
ReentrantLock是一種可重入鎖,可以進行重複加鎖,最常用的操作是使用lock()方法來獲取鎖,在使用完畢後再通過unlock()方法釋放鎖。使用ReentrantLock還可以配合Condition來實現線程等待和線程喚醒的機制。示例代碼如下:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockExample { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); private int count = 0; public void addCount() { try { lock.lock(); count++; System.out.println(Thread.currentThread().getName() + "獲得鎖,count值增加為" + count); condition.signalAll(); } finally { lock.unlock(); } } public void subCount() { try { lock.lock(); while (count <= 0) { condition.await(); } count--; System.out.println(Thread.currentThread().getName() + "獲得鎖,count值減少為" + count); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } // 省略其他方法 }
上述示例中,我們使用lock()方法獲取鎖,並在使用完畢後通過unlock()方法釋放鎖。在addCount()方法中,我們使用signalAll()方法來喚醒等待線程。在subCount()方法中,我們使用await()方法來等待條件滿足並獲取鎖。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/290743.html