更新時間:2022-12-28 12:18:39 來源:動力節點 瀏覽1990次
Java線程鎖有哪幾種?動力節點小編來告訴大家。java特性的鎖只有兩種,volatile和synchronized,其他的都是lib包實現。
對象鎖,指定對象加鎖,鑰匙有且只有一個,線程之間會競爭這個鑰匙,誰拿到先誰就可以進入,完事后歸還該鎖,循環往復。沒爭搶到的則被阻塞。
程序員沒法控制這種鎖的狀態,線程獲取鎖后中斷導致被鎖對象死鎖,并且極端情況程序間相互調用產生互斥。
用法
class Lock{
//因為靜態method加載順序比class優先,所以靜態方法中需要反射
public static synchronized void Test3() {
synchronized(Lock.class){
//todo
}
}
//本質是鎖當前方法
public synchronized void Test1() {
//todo
}
//鎖lockObj屬性
private Boolean lockObj = true;
public synchronized void Test2() {
synchronized(lockObj){
//todo
}
}
}
針對synchronized的弊端,延伸出可控制獲取鎖狀態的類,使得鎖的獲取和釋放可在代碼中控制,那意味著可在finally中釋放,避免程序異常導致死鎖。
class Counter {
private final Lock lock = new ReentrantLock();
private int count;
//程序異常可以釋放鎖,防止形成死鎖
public void add(int n) {
lock.lock();
try {
count += n;
} finally {
lock.unlock();
}
}
//嘗試獲取鎖,超時返回false
public void add2(int n) throws InterruptedException {
if (lock.tryLock(1, TimeUnit.SECONDS)) {
try {
//todo
} finally {
lock.unlock();
}
}
}
}
這種鎖是優化reentrantlock的使用,reentrantlock是針對線程訪問的鎖,ReadWriteLock是針對讀寫操作細分的鎖,它可以更精細化的控制鎖的粒度。讀寫鎖分離。
public class Counter {
private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
private final Lock rlock = rwlock.readLock();
private final Lock wlock = rwlock.writeLock();
public void inc(int index) {
wlock.lock(); // 加寫鎖
try {
//todo
} finally {
wlock.unlock(); // 釋放寫鎖
}
}
public int[] get() {
rlock.lock(); // 加讀鎖
try {
//todo
} finally {
rlock.unlock(); // 釋放讀鎖
}
}
}
這種鎖在你讀的過程中不允許寫入,StampedLock和ReadWriteLock相比,讀寫鎖是可以讀鎖和寫鎖一起獲取,同時讀寫的,但是StampedLock不允許同時讀寫
說這個鎖之前,先解釋下為什么會有線程不安全,線程操作一個共享資源的值時候,會把這個資源重內存加載到cpu寄存器(高速緩存),然后操作完成會刷回內存,并發過程中,多個線程一起拿一起操作同一個值,一起刷回去,就導致了操作不冪等了。
有了這個概念就很好解釋volatile,它實際就是讓你的資源在cpu高速緩存中保證一致性,但也存在弊端,被volatile鎖的資源如果操作中含有其他共享資源(包括它自己)也會導致線程不安全。
class VolatileCounter{
//正確打開方式
private Boolean status;
public void open(){
status = true;
}
public void close(){
status = false;
}
//錯誤例子
private Integer otherShareNumber; //該對象被其他線程操作
private volatile Integer number;
public void add(){
number = number + 1;
number = otherShareNumber + 1;
}
}
X是各種類型,底層也是基于volatile,這里引入樂觀鎖的概念,每次更新時候都比對一下舊值,舊值一樣才允許更新,否則再來一遍,直到更新成功為止。
public int incrementAndGet(AtomicInteger var) {
int prev, next;
do {
prev = var.get();
next = prev + 1;
} while ( ! var.compareAndSet(prev, next));
return next;
}
以上就是關于“Java線程鎖有哪幾種”的介紹,大家如果對此比較感興趣,可以關注一下本站的Java視頻教程,里面的課程內容細致全面,通俗易懂,很適合沒有基礎的小伙伴學習,希望對大家能夠有所幫助。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習