[英]How can 2 threads access a synchronized block at the same time?
您能描述一下在多線程環境中以下代碼是如何正常工作的嗎? 我從https://www.javacodegeeks.com/2014/11/multithreading-concurrency-interview-questions-answers.html獲取了代碼。 描述說2個線程可能一個接一個地進入第二個同步塊。 怎么會這樣 有兩個同步塊有什么關系?
public Integer getNextInt() {
Integer retVal = null;
synchronized (queue) {
try {
while (queue.isEmpty()) {
queue.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (queue) {
retVal = queue.poll();
if (retVal == null) {
System.err.println("retVal is null");
throw new IllegalStateException();
}
}
return retVal;
}
這很簡單-第一個同步塊(S1)使線程等待,直到隊列變為非空。 第二個同步塊(S2)使單個線程從隊列中獲取一項。
如您所見,只有1個線程按預期進入了同步塊,但這不能保證正確的同步。
使用同步塊的全部目的是圍繞必須一起執行的代碼段創建“事務”。 沒有機會在“中間”插入另一個線程。
您的示例有兩個街區; 並且很可能第一個線程離開了第一個塊; 但是第二個線程進入,第一個線程可以進入第二個塊。
這就是全部。
queue.wait()
釋放鎖定,該鎖定將應用於同步塊。 換句話說,當queue.wait()
時,其他線程可以自由進入同步塊。 下面,我提供了一個工作示例,其中5個線程同時輸入相同的同步塊。 您可以檢查以下代碼,以了解wait
()和notiy()/ notifyAll()
方法如何工作:
public class Main {
static Object lock = new Object();
public static void main(String args[]) throws InterruptedException {
Runnable r = () -> {
System.out.println(" ThreadID: " + Thread.currentThread().getId() + " has started");
synchronizedBlockExecution();
};
for (int i = 0; i < 5; i++) {
Thread t = new Thread(r);
t.start();
}
Thread.sleep(1000);
System.out.println("------all threads are notifed to stop waiting!---------");
synchronized (lock) {
lock.notifyAll();
}
}
public static void synchronizedBlockExecution() {
System.out.println("Thread: " + Thread.currentThread().getId() + " is entering synchronized block");
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread: " + Thread.currentThread().getId() + " has left synchronized block");
}
}
T1進入S1
T1存在S1
T2等待T1從S1完成
T1完成並進入S2
S1對於T2是免費的
T2進入S1
這樣,T1和T2可以同時處於兩個不同的同步塊中。 這將提高性能。 程序員應該編寫同步塊而不是方法,因為它允許兩個線程同時在兩個單獨的塊中工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.