在Java編程中,鎖是一個(gè)很基本的概念,用來(lái)在多線程環(huán)境下對(duì)共享資源進(jìn)行同步訪問(wèn)。對(duì)于鎖的使用場(chǎng)景,一般可以分為兩類(lèi):樂(lè)觀鎖和悲觀鎖。
樂(lè)觀鎖是一種相對(duì)比較輕量級(jí)的鎖策略,其核心思想就是假設(shè)多個(gè)線程訪問(wèn)共享資源時(shí)不會(huì)發(fā)生沖突,因此,在讀取數(shù)據(jù)時(shí)不加鎖,在寫(xiě)入數(shù)據(jù)時(shí)采用CAS(比較交換)算法進(jìn)行版本控制,以保證并發(fā)修改時(shí)的數(shù)據(jù)正確性。
public class OptimisticLockDemo { private int count = 0; private AtomicInteger atomicCount = new AtomicInteger(0); public void increase() { int newValue = atomicCount.incrementAndGet(); if (newValue >10) { throw new RuntimeException("超過(guò)最大值"); } count++; System.out.println(Thread.currentThread().getName() + " count:" + count + " newValue:" + newValue); } }
上述代碼中,使用AtomicInteger進(jìn)行計(jì)數(shù),版本控制在incrementAndGet()方法中完成。
相較于樂(lè)觀鎖,悲觀鎖則是一種更加保守、更加安全的鎖策略。其核心思想就是認(rèn)為在多線程環(huán)境下一定會(huì)發(fā)生沖突,因此,在讀取和寫(xiě)入數(shù)據(jù)時(shí)都需要加鎖,以防止并發(fā)修改時(shí)的數(shù)據(jù)錯(cuò)誤。
public class PessimisticLockDemo { private static int count = 0; public static synchronized void increase() { count++; System.out.println(Thread.currentThread().getName() + " count:" + count); } }
上述代碼中,使用synchronized關(guān)鍵字保證線程同步。
需要注意的是,悲觀鎖會(huì)比樂(lè)觀鎖占用更多的資源,因此在性能敏感的場(chǎng)景中應(yīng)盡量采用樂(lè)觀鎖,而在一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu)操作中,悲觀鎖可能是唯一的選擇。