[英]How can 2 threads access a synchronized block at the same time?
Can you describe how in a multithreaded environment, the below code works incorrectly? 您能描述一下在多线程环境中以下代码是如何正常工作的吗? I took the code from https://www.javacodegeeks.com/2014/11/multithreading-concurrency-interview-questions-answers.html . 我从https://www.javacodegeeks.com/2014/11/multithreading-concurrency-interview-questions-answers.html获取了代码。 The description says 2 threads may enter the 2nd synchronized block one after the other. 描述说2个线程可能一个接一个地进入第二个同步块。 How can this happen? 怎么会这样 What is the relation by having 2 synchronized blocks? 有两个同步块有什么关系?
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;
}
It's pretty simple - the first synchronized block (S1) makes a thread wait until the queue becomes non-empty. 这很简单-第一个同步块(S1)使线程等待,直到队列变为非空。 The second synchronized block (S2) makes a single thread take an item from the queue. 第二个同步块(S2)使单个线程从队列中获取一项。
As you can see, only 1 thread enters a synchronized block as expected, but this does not guarantee proper synchronization. 如您所见,只有1个线程按预期进入了同步块,但这不能保证正确的同步。
The whole point of using a synchronized block is to create a "transaction" around pieces of code that must be executed together; 使用同步块的全部目的是围绕必须一起执行的代码段创建“事务”。 without the chance of another thread coming in "in between". 没有机会在“中间”插入另一个线程。
Your example has two blocks; 您的示例有两个街区; and it is very well possible that a first thread leaves the first block; 并且很可能第一个线程离开了第一个块; but a second thread kicks in before the first thread can enter the second block. 但是第二个线程进入,第一个线程可以进入第二个块。
That is all there is to this. 这就是全部。
queue.wait()
releases the lock, which is applied on synchronized block. queue.wait()
释放锁定,该锁定将应用于同步块。 In other words, when queue.wait()
is reached, other threads are free to enter the synchronized block. 换句话说,当queue.wait()
时,其他线程可以自由进入同步块。 Below I include the working example, in which 5 threads enter the same synchronized block at the same time. 下面,我提供了一个工作示例,其中5个线程同时输入相同的同步块。 You can inspect this code to get a feeling how wait
() and notiy()/ notifyAll()
methods work: 您可以检查以下代码,以了解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 enters S1 T1进入S1
T1 exists S1 T1存在S1
T2 wait for T1 to complete from S1 T2等待T1从S1完成
T1 completes and enters S2 T1完成并进入S2
S1 is free for T2 S1对于T2是免费的
T2 enters S1 T2进入S1
In this ways T1 and T2 can be in two different synchronize block at a time. 这样,T1和T2可以同时处于两个不同的同步块中。 This will improve performance. 这将提高性能。 Programmer should write synchronize block instead of methods as it allows two thread to work in two separate block at a time. 程序员应该编写同步块而不是方法,因为它允许两个线程同时在两个单独的块中工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.