java 同步 lock_关于java:同步是否像Lock.lock()一样驻留并发线程?
當(dāng)我們調(diào)用lock.lock()或嘗試輸入synchronized塊時,如果其他某個線程已經(jīng)獲得了該鎖,則我們的線程將阻塞。 現(xiàn)在我的問題是,當(dāng)我們查看lock.lock()的實(shí)現(xiàn)時,它會將獲取鎖委托給AQS,而AQS實(shí)際將當(dāng)前線程駐留在該線程中(因此調(diào)度程序無法對其進(jìn)行進(jìn)一步調(diào)度)。
synchronized阻塞是否也是如此?
我什至認(rèn)為我的線程狀態(tài)也不同。 例如,如果我的線程在synchronized塊上被阻塞,則它將是BLOCKING,而如果我調(diào)用了
lock.lock(),則為WAITING。 我對嗎?
我關(guān)心的是以下兩種鎖定策略在Thread.status方面與通過停車而不是忙于等待來提高性能之間的區(qū)別
ReentrantLock.lock();
synchronize { /*some code */ }
抱歉,我從自動翻譯器回復(fù)。 我認(rèn)為您應(yīng)該附加示例代碼,這將幫助我們幫助您分析問題。 一般在使用同步時,可以不必鎖定。 鎖 ()。 一般來說,足夠同步。
調(diào)用lock或lockInterruptibly會將線程置于WAITING狀態(tài):
Thread state for a waiting thread. A thread is in the waiting state due to calling one of the following methods:
Object.wait with no timeout
Thread.join with no timeout
LockSupport.park
以下代碼啟動四個線程,前兩個(A,B)運(yùn)行相同的代碼,并通過lock方法鎖定某些監(jiān)視器。 另外兩個(C,D)也運(yùn)行相同的代碼,但是它們通過lockInterruptibly方法鎖定了另一個監(jiān)視器:
public static synchronized void dumpThreadState(List threads) {
System.out.println("thread state dump start");
for (Thread t: threads) {
System.out.println(t.getName()+""+t.getState());
}
System.out.println("thread state dump end\
");
}
public static void main(String[] args) throws InterruptedException {
final Lock lock = new ReentrantLock();
final Lock anotherLock = new ReentrantLock();
List threads = new LinkedList();
Runnable first = new Runnable() {
@Override
public void run() {
try {
lock.lock();
}
catch (Exception ex) {
System.out.println(Thread.currentThread().getName()+" processing exception"+ex.getClass().getSimpleName());
}
while (true);
}
} ;
Runnable second = new Runnable() {
@Override
public void run() {
try {
anotherLock.lockInterruptibly();
}
catch (InterruptedException ex) {
System.out.println(Thread.currentThread().getName()+" was interrupted");
}
while (true);
}
};
threads.add(new Thread(first,"A"));
threads.add(new Thread(first,"B"));
threads.add(new Thread(second,"C"));
threads.add(new Thread(second,"D"));
dumpThreadState(threads);
for (Thread t: threads) {
t.start();
}
Thread.currentThread().sleep(100);
dumpThreadState(threads);
System.out.println("interrupting" + threads.get(1).getName());
threads.get(1).interrupt();
dumpThreadState(threads);
System.out.println("interrupting" + threads.get(3).getName());
threads.get(3).interrupt();
Thread.currentThread().sleep(100);
dumpThreadState(threads);
for (Thread t: threads) {
t.join();
}
}
它輸出:
thread state dump start
A NEW
B NEW
C NEW
D NEW
thread state dump end
thread state dump start
A RUNNABLE
B WAITING
C RUNNABLE
D WAITING
thread state dump end
interrupting B
thread state dump start
A RUNNABLE
B WAITING
C RUNNABLE
D WAITING
thread state dump end
interrupting D
D was interrupted
thread state dump start
A RUNNABLE
B WAITING
C RUNNABLE
D RUNNABLE
thread state dump end
可以看出,通過lock方法鎖定的線程不能被中斷,而通過lockInterruptibly鎖定的線程可以被中斷。
在另一個示例中,啟動了三個線程,前兩個(A,B)運(yùn)行相同的代碼,并通過synchronized塊鎖定在同一監(jiān)視器上。 第三個線程鎖定在另一個監(jiān)視器上,但通過wait方法等待:
public static void main(String[] args) throws InterruptedException {
final Object lock = new Object();
final Object anotherLock = new Object();
List threads = new LinkedList();
Runnable first = new Runnable() {
@Override
public void run() {
synchronized(lock) {
while (true);
}
}
} ;
Runnable second = new Runnable() {
@Override
public void run() {
synchronized(anotherLock) {
try {
anotherLock.wait();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
};
threads.add(new Thread(first,"A"));
threads.add(new Thread(first,"B"));
threads.add(new Thread(second,"C"));
dumpThreadState(threads);
for (Thread t: threads) {
t.start();
}
Thread.currentThread().sleep(100);
dumpThreadState(threads);
for (Thread t: threads) {
t.join();
}
}
它輸出:
thread state dump start
A NEW
B NEW
C NEW
thread state dump end
thread state dump start
A RUNNABLE
B BLOCKED
C WAITING
thread state dump end
線程C以WAITING狀態(tài)結(jié)束,而線程B以BLOCKING狀態(tài)結(jié)束:
Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait.
編輯:
這是一個非常好的線程狀態(tài)的UML圖。
阻止-在資源上被阻止,無法被中斷
等待-在資源上被阻止,但可以被中斷,通知或取消停放。
如您所見,Waiting更好地控制了另一個處理程序。例如如果兩個線程死鎖,則可以通過中斷來中斷l(xiāng)ock()。使用同步的兩個線程時,您將陷入困境。
同步vs鎖定的行為非常相似,確切的細(xì)節(jié)在主要版本之間有所不同。
我的建議是使用
同步以獲取需要線程安全但鎖爭用非常低的簡單代碼。
在已確定有鎖爭用的地方使用Lock,或者需要其他功能,例如tryLock。
如果你這樣做
final Lock lock = new ReentrantLock();
lock.lock();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(100);
System.out.println(t +" is" + t.getState());
lock.unlock();
版畫
Thread[Thread-0,5,main] is WAITING
Thread.State狀態(tài)
等待線程的線程狀態(tài)。由于調(diào)用以下方法之一,線程處于等待狀態(tài):
Object.wait沒有超時
Thread.join沒有超時
LockSupport.park
處于等待狀態(tài)的線程正在等待另一個線程執(zhí)行特定操作。例如,一個在對象上調(diào)用Object.wait()的線程正在等待另一個線程在該對象上調(diào)用Object.notify()或Object.notifyAll()。名為Thread.join()的線程正在等待指定的線程終止。
謝謝@Peter Lawrey,當(dāng)線程被lock.lock()阻塞時,線程的狀態(tài)如何?
好的一點(diǎn)是,lock()將被阻塞,而lockInterruptably()將被等待,因?yàn)樗梢员恢袛唷?/p>
@PeterLawrey調(diào)用鎖也會使線程也處于等待狀態(tài)
駐留線程和同步阻塞是非常不同的。嘗試輸入同步塊時,您將明確嘗試在對象實(shí)例上獲取監(jiān)視器。如果無法獲取監(jiān)視器,則線程將進(jìn)入"阻塞"狀態(tài),直到監(jiān)視器可用為止。停放與Object.wait()方法更相似,因?yàn)榇a知道在其他條件變?yōu)檎嬷八荒芾^續(xù)。阻止在這里是沒有意義的,因?yàn)檫@將是徒勞的,因?yàn)槲夷壳袄^續(xù)的條件是正確的。此時,我進(jìn)入WAITING或TIMED_WAITING狀態(tài)(取決于等待的發(fā)出方式),直到被通知(通過類似notify(),notifyAll()或unpark()的通知)為止。一旦我的條件變?yōu)檎?#xff0c;我就進(jìn)入等待狀態(tài),然后可能會嘗試獲取監(jiān)視器并在需要時進(jìn)入阻塞狀態(tài)。如果我得到顯示器,則進(jìn)入"運(yùn)行"并繼續(xù)快樂地前進(jìn)
因此,等待實(shí)際上就是知道我無法做某事,并在認(rèn)為可以的情況下讓其他線程通知我。我醒來后可能導(dǎo)致阻塞。阻塞只是爭奪對監(jiān)視器的訪問,而沒有其他明確的先決條件。
在Lock實(shí)例上調(diào)用lock()時,調(diào)用線程實(shí)際上處于等待狀態(tài),并且沒有阻塞。這樣做的好處是可以中斷此等待狀態(tài),這有助于避免死鎖。對于類似Lock類的東西,您可以通過tryLock(),tryLock(long,TimeUnit),lock()和lockInterruptibly()來選擇所需的等待行為。您可以指定諸如要等待多長時間以及是否可以通過調(diào)用哪種方法打擾您之類的事情。使用synchronized代碼,您沒有此類選項(xiàng)。您正在阻塞,并且被阻塞阻塞,直到某個線程放棄了您想要的監(jiān)視器為止,如果從未中斷,您將陷入僵局。這就是為什么從Java 5和concurrent包開始,您應(yīng)該避免使用synchronized關(guān)鍵字,而是嘗試使用Lock和Condition之類的東西實(shí)現(xiàn)類似的語義。
謝謝@ cmbaxter,實(shí)際上我想問的是,當(dāng)它調(diào)用Reentrantlock.lock()時,線程實(shí)際上進(jìn)入了停車狀態(tài)。 這就是為什么我的問題在ReentrantLock.lock()中被阻止的原因?qū)嶋H上并未被阻止
是的,如果鎖當(dāng)前不可用,則調(diào)用lock會將調(diào)用線程置于WAITING狀態(tài)。
總結(jié)
以上是生活随笔為你收集整理的java 同步 lock_关于java:同步是否像Lock.lock()一样驻留并发线程?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTML 标记一览
- 下一篇: 几件欣慰的事,关于.Net的培训和嵌入式