在Java中,鎖(Lock)是一種用于控制多個線程對共享資源訪問的機制。通過使用鎖,可以確保在同一時間只有一個線程能夠訪問共享資源,從而避免數據競爭和不一致性問題。Java提供了多種鎖機制,包括內置的synchronized
關鍵字和java.util.concurrent.locks
包中的顯式鎖。
synchronized
關鍵字synchronized
是Java中最基本的鎖機制,它可以用于方法或代碼塊,確保同一時間只有一個線程能夠執行被鎖定的代碼。
通過在方法聲明中添加synchronized
關鍵字,可以將整個方法鎖定。當一個線程進入該方法時,其他線程必須等待該線程退出方法后才能進入。
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
synchronized
也可以用于代碼塊,鎖定特定的對象。這種方式比同步方法更靈活,因為它允許你只鎖定需要同步的部分代碼。
public class Counter {
private int count = 0;
private final Object lock = new Object();
public void increment() {
synchronized (lock) {
count++;
}
}
public int getCount() {
synchronized (lock) {
return count;
}
}
}
ReentrantLock
ReentrantLock
是java.util.concurrent.locks
包中的一個顯式鎖實現。與synchronized
相比,ReentrantLock
提供了更多的功能,如可中斷的鎖獲取、超時鎖獲取、公平鎖等。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Counter {
private int count = 0;
private final Lock lock = new ReentrantLock();
public void increment() {
lock.lock(); // 獲取鎖
try {
count++;
} finally {
lock.unlock(); // 釋放鎖
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
ReentrantLock
允許線程在等待鎖的過程中被中斷,這在某些情況下非常有用。
public void incrementInterruptibly() throws InterruptedException {
lock.lockInterruptibly(); // 可中斷的鎖獲取
try {
count++;
} finally {
lock.unlock();
}
}
ReentrantLock
還支持超時鎖獲取,即線程在指定的時間內嘗試獲取鎖,如果超時則放棄。
public boolean incrementWithTimeout(long timeout, TimeUnit unit) throws InterruptedException {
if (lock.tryLock(timeout, unit)) { // 嘗試獲取鎖,超時則返回false
try {
count++;
return true;
} finally {
lock.unlock();
}
}
return false;
}
ReentrantLock
可以配置為公平鎖,即按照線程請求鎖的順序來分配鎖。默認情況下,ReentrantLock
是非公平的。
private final Lock fairLock = new ReentrantLock(true); // 公平鎖
ReadWriteLock
ReadWriteLock
是一種特殊的鎖,它允許多個讀線程同時訪問共享資源,但在寫線程訪問時,所有讀線程和其他寫線程都會被阻塞。ReentrantReadWriteLock
是ReadWriteLock
的一個實現。
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class SharedResource {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private int data = 0;
public void readData() {
rwLock.readLock().lock();
try {
System.out.println("Read data: " + data);
} finally {
rwLock.readLock().unlock();
}
}
public void writeData(int newData) {
rwLock.writeLock().lock();
try {
data = newData;
System.out.println("Write data: " + data);
} finally {
rwLock.writeLock().unlock();
}
}
}
StampedLock
StampedLock
是Java 8引入的一種新的鎖機制,它提供了更細粒度的鎖控制,并且在某些場景下性能優于ReadWriteLock
。
import java.util.concurrent.locks.StampedLock;
public class SharedResource {
private final StampedLock stampedLock = new StampedLock();
private int data = 0;
public void readData() {
long stamp = stampedLock.tryOptimisticRead();
int currentData = data;
if (!stampedLock.validate(stamp)) {
stamp = stampedLock.readLock();
try {
currentData = data;
} finally {
stampedLock.unlockRead(stamp);
}
}
System.out.println("Read data: " + currentData);
}
public void writeData(int newData) {
long stamp = stampedLock.writeLock();
try {
data = newData;
System.out.println("Write data: " + data);
} finally {
stampedLock.unlockWrite(stamp);
}
}
}
Java提供了多種鎖機制來滿足不同的并發需求。synchronized
是最簡單的鎖機制,適用于大多數場景。ReentrantLock
提供了更多的功能和靈活性,適用于需要更復雜控制的場景。ReadWriteLock
和StampedLock
則適用于讀多寫少的場景,能夠提高并發性能。
在選擇鎖機制時,應根據具體的應用場景和需求來決定使用哪種鎖。合理使用鎖可以有效地避免并發問題,提高程序的性能和穩定性。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。