在Java面試中,經常會被問到關于樂觀鎖和悲觀鎖的區別。這兩種鎖機制是在并發操作中用來保證數據一致性的重要方法。
悲觀鎖通常采用“先獲取鎖再執行操作”的方式,它的核心思想是認為在并發環境下,數據很有可能會被其他線程修改,因此在訪問數據之前先加鎖保證數據的獨占性。在Java中,synchronized關鍵字和ReentrantLock都是悲觀鎖常用的實現方式。
synchronized(Object obj) { //獲取鎖 ... //執行操作 ... //釋放鎖 }
ReentrantLock lock = new ReentrantLock(); lock.lock(); try { //執行操作 } finally { lock.unlock(); }
相反地,樂觀鎖則采用“先執行操作再校驗”的方式,它假設并發情況下數據可能不會被修改,因此不會立即加鎖,而是在更新數據時校驗數據是否被其他線程修改過。如果沒有,則執行更新操作;如果有,則進行相應處理。在Java中,CAS算法(比較并交換)是樂觀鎖的經典實現方式。
public class AtomicInteger { private volatile int value; public final int get() { return value; } public final void set(int newValue) { value = newValue; } public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return current; } } public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } }
總的來說,悲觀鎖在多線程環境下加鎖保證數據的獨占性,但其并發性較差,可能帶來性能問題。而樂觀鎖不存在鎖競爭問題,不會出現死鎖,但需要注意線程安全問題和ABA問題。具體區別需要根據業務場景進行選擇。
上一篇java頁面和元模型
下一篇ajax表單動態獲取數據