一、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
微信掃一掃
支付寶掃一掃