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