英文:
Significance of use of keyword synchronized in the following code
问题
以下是您要翻译的内容:
我正在从Herbert Schildt的书《Java完全参考》1中阅读有关Java中的多线程。我遇到了以下代码*[第252页,第7版]*,该代码解释了在现代Java中使用wait()
和notify()
来挂起和恢复线程的用法。我的问题与以下代码中的两个地方的关键字synchronization
的重要性有关(在NewThread
类的run()
方法中):
// 以现代方式挂起和恢复线程。
class NewThread implements Runnable {
String name;
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
suspendFlag = false;
t.start();
}
// 这是线程的入口点。
public void run() {
try {
for (int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized (this) { // 这里是第一个疑问
while (suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() { // 这里是第二个疑问
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
Thread.sleep(1000);
ob1.myresume();
ob2.mysuspend();
Thread.sleep(1000);
ob2.myresume();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
// 一些代码
}
我的疑问:我知道关键字synchronization
的用途,即只允许一个线程在同一个对象上进入同步方法,但在这里我们有两个线程在两个不同的对象上运行。因此,以上代码中使用的两个synchronization
关键字的重要性是什么。
我尝试删除不同位置的Synchronization
关键字并同时运行以上代码。我得到了相同的错误:java.lang.IllegalMonitorStateException: current thread is not owner
,错误次数和行数不同,具体取决于我是否删除了两个关键字中的哪一个以及删除哪一个。我查找了上述错误,并在这里找到了一个解释,但仍然无法与我的疑问联系起来。
英文:
I was reading multi threading
in Java
from the book Java The Complete Reference by Herbert Schildt. I came across following code [Pg. 252, 7th ed.] that explained the usage of wait()
and notify()
to suspend
and resume
threads in modern Java
. My question is regarding the significance of the keyword synchronization
at two places in following code (in run()
method of class NewThread
):
// Suspending and resuming a thread the modern way.
class NewThread implements Runnable {
String name;
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
suspendFlag = false;
t.start();
}
// This is the entry point for thread.
public void run() {
try {
for (int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized (this) { //First doubt here
while (suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() { //Second doubt here
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
Thread.sleep(1000);
ob1.myresume();
ob2.mysuspend();
Thread.sleep(1000);
ob2.myresume();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
//some code
}
My doubt here: I know about the use of keyword synchronization
i.e. allowing only one thread to enter a synchronized method on the same object but here we have two threads running on two different objects. So what is the significance of both synchronization
keywords used in above code.
I tried running the above code by removing the synchronized
keyword at each place differently and simultaneously. I am getting the same error: java.lang.IllegalMonitorStateException: current thread is not owner
different number of times and at different line numbers depending upon if I remove both or only one (and which one) synchronization
keyword. I looked for the above error and found an explanation for it here but still couldn't connect the answer to my doubt.
答案1
得分: 0
synchronized
解决的问题是它允许两个线程对共享的 suspendFlag
变量有一致的视图。
在一些实际程序中,一个线程可能在将 susependFlag=false
设置之前设置其他共享变量。如果没有使用 synchronized
,那么等待的线程可能会唤醒,并且看到 suspendFlag==false
,但是不会看到其他变量被设置。或者更糟糕的是,它可能看到其中一些被设置,但其他的没有。
在没有同步的情况下,Java 不保证不同的线程会以相同的顺序看到变量的更新。
我得到了相同的错误:java.lang.IllegalMonitorStateException: 当前线程不是所有者。
Java 库试图通过 强制 你在允许使用 wait()
和 notify()
之前使用 synchronized
来帮助你。规则很简单:只有在位于 synchronized(o)
块内的代码中才能调用 o.wait()
、o.notify()
或 o.notifyAll()
。如果你违反这个规则,那么库会抛出异常。
当你的代码调用 o.wait()
时,wait() 调用会临时 解锁 监视器锁,以便其他线程能够对 o
进行同步并调用 o.notify()
。o.wait()
调用保证在返回之前重新锁定 o
。
英文:
The problem that synchronized
solves is, it allows the two threads to have a consistent view of the shared suspendFlag
variable.
In some real program, a thread might set other shared variables before setting susependFlag=false
. If synchronized
was not used, then the waiting thread could wake up, and see suspendFlag==false
, but not see the other variables set. Or worse, it could see some of them set, but not others.
Without synchronization, Java does not guarantee that different threads will see variables updated in the same order.
> I am getting the same error: java.lang.IllegalMonitorStateException: current thread is not owner.
The Java library is trying to help you by forcing you to use synchronized
before it will allow you to use wait()
and notify()
. The rule is simple: You can only call o.wait()
or o.notify()
or o.notifyAll()
from code that is inside a synchronized(o)
block. If you break that rule, then the library throws the exception.
When your code calls o.wait()
the wait() call temporarily unlocks the monitor lock so that the other thread will be able to synchronize on o
and call o.notify()
. The o.wait()
call is guaranteed to re-lock o
before it returns.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论