本文目錄一覽:
- 1、java synchronized對靜態方法加鎖
- 2、java中多線程使用lock鎖 其中一個使用unlock方法為什麼鎖就失效了
- 3、java中synchronized函數鎖,鎖的是什麼?
- 4、java 對象鎖和方法鎖有什麼區別
java synchronized對靜態方法加鎖
2所有的非靜態同步方法用的都是同一把鎖——實例對象本身,也就是說如果一個實例對象的非靜態同步方法獲取鎖後,該實例對象的其他非靜態同步方法必須等待獲取鎖的方法釋放鎖後才能獲取鎖,可是別的實例對象的非靜態同步方法因為跟該實例對象的非靜態同步方法用的是不同的鎖,所以毋須等待該實例對象已獲取鎖的非靜態同步方法釋放鎖就可以獲取他們自己的鎖。
而所有的靜態同步方法用的也是同一把鎖——類對象本身,這兩把鎖是兩個不同的對象,所以靜態同步方法與非靜態同步方法之間是不會有競態條件的。但是一旦一個靜態同步方法獲取鎖後,其他的靜態同步方法都必須等待該方法釋放鎖後才能獲取鎖,而不管是同一個實例對象的靜態同步方法之間,還是不同的實例對象的靜態同步方法之間,只要它們同一個類的實例對象!
java中多線程使用lock鎖 其中一個使用unlock方法為什麼鎖就失效了
Java中Lock,tryLock,lockInterruptibly的區別如下:
一、 lock()方法
使用lock()獲取鎖,若獲取成功,標記下是該線程獲取到了鎖(用於鎖重入),然後返回。若獲取失敗,這時跑一個for循環,循環中先將線程阻塞放入等待隊列,當被調用signal()時線程被喚醒,這時進行鎖競爭(因為默認使用的是非公平鎖),如果此時用CAS獲取到了鎖那麼就返回,如果沒獲取到那麼再次放入等待隊列,等待喚醒,如此循環。其間就算外部調用了interrupt(),循環也會繼續走下去。一直到當前線程獲取到了這個鎖,此時才處理interrupt標誌,若有,則執行 Thread.currentThread().interrupt(),結果如何取決於外層的處理。lock()最終執行的方法如下:
[java] view plain copy
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head tryAcquire(arg)) { //如果競爭得到了鎖
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted; //獲取成功返回interrupted標誌
}
// 只修改標誌位,不做其他處理
if (shouldParkAfterFailedAcquire(p, node) parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
其中parkAndCheckInterrupt()調用了LockSupport.park(),該方法使用Unsafe類將進程阻塞並放入等待隊列,等待喚醒,和await()有點類似。
可以看到循環中檢測到了interrupt標記,但是僅做 interrupted = true 操作,直到獲取到了鎖,才return interrupted,然後處理如下
[java] view plain copy
public final void acquire(int arg) {
if (!tryAcquire(arg) acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt(); // 執行Thread.currentThread().interrupt()
}
二、 lockInterruptibly()方法
和lock()相比,lockInterruptibly()只有略微的修改,for循環過程中,如果檢測到interrupt標誌為true,則立刻拋出InterruptedException異常,這時程序變通過異常直接返回到最外層了,又外層繼續處理,因此使用lockInterruptibly()時必須捕捉異常。lockInterruptibly()最終執行的方法如下:
[java] view plain copy
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return; //獲取成功返回
}
if (shouldParkAfterFailedAcquire(p, node)
parkAndCheckInterrupt())
throw new InterruptedException(); //直接拋出異常
}
} finally {
if (failed)
cancelAcquire(node);
}
}
三、 tryLock()方法
使用tryLock()嘗試獲取鎖,若獲取成功,標記下是該線程獲取到了鎖,然後返回true;若獲取失敗,此時直接返回false,告訴外層沒有獲取到鎖,之後的操作取決於外層,代碼如下:
[java] view plain copy
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc 0) // overflow
throw new Error(“Maximum lock count exceeded”);
setState(nextc);
return true;
}
return false;
}
java中synchronized函數鎖,鎖的是什麼?
修飾方法就代表鎖的是此方法體,如 public synchronized int cal(){…} 表示每次訪問此方法都只能一個線程訪問,其他的要等待訪問完了才能進入此方法,這是競爭鎖,synchronized(obj)鎖的是obj,代表只有獲取了此obj鎖,才能繼續訪問,更高級的推薦使用Lock或ReentrainLock。
java 對象鎖和方法鎖有什麼區別
對象鎖類鎖
對象鎖
當一個對象中有synchronized
method或synchronized
block的時候調用此對象的同步方法或進入其同步區域時,就必須先獲得對象鎖。如果此對象的對象鎖已被其他調用者佔用,則需要等待此鎖被釋放
同步靜態方法/靜態變量互斥體
由於一個class不論被實例化多少次,其中的靜態方法和靜態變量在內存中都只由一份。所以,一旦一個靜態的方法被申明為synchronized。此類所有的實例化對象在調用此方法,共用同一把鎖,我們稱之為類鎖。一旦一個靜態變量被作為synchronized
block的mutex。進入此同步區域時,都要先獲得此靜態變量的對象鎖
類鎖
由上述同步靜態方法引申出一個概念,那就是類鎖。其實系統中並不存在什麼類鎖。當一個同步靜態方法被調用時,系統獲取的其實就是代表該類的類對象的對象鎖
在程序中獲取類鎖
可以嘗試用以下方式獲取類鎖
synchronized
(xxx.class)
{…}
synchronized
(Class.forName(“xxx”))
{…}
同時獲取2類鎖
同時獲取類鎖和對象鎖是允許的,並不會產生任何問題,但使用類鎖時一定要注意,一旦產生類鎖的嵌套獲取的話,就會產生死鎖,因為每個class在內存中都只能生成一個Class實例對象。
原創文章,作者:XSTUP,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/330331.html