我尝试了解java核心同步。
我写了代码示例:
程序应该写
左 右
10次
package concurrency;
public class LeftRightWaitNotifyExample {
final static String str = "1";
public static void main(String[] args) {
new LeftLegThread(str).start();
new RightLegThread(str).start();
}
}
class LeftLegThread extends Thread {
String monitor;
public LeftLegThread(String str) {
monitor = str;
}
@Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
for (int i = 0; i < 10; i++) {
System.out.println("Left ");
wait();
}
}
}
}
class RightLegThread extends Thread {
String monitor;
public RightLegThread(String str) {
monitor = str;
}
@Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
while (true) {
System.out.println("Right ");
notify();
wait();
}
}
}
}
我得到了这个输出:
Left
Right
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at concurrency.LeftLegThread.makeStep(LeftRightWaitNotifyExample.java:35)
at concurrency.LeftLegThread.run(LeftRightWaitNotifyExample.java:23)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at concurrency.RightLegThread.makeStep(LeftRightWaitNotifyExample.java:61)
at concurrency.RightLegThread.run(LeftRightWaitNotifyExample.java:51)
当我在wait
块中使用synchronized
方法时出现此错误之前。但是我在synchronized
块中使用等待
问题的原因是什么以及如何解决?
我根据建议改写代码:
public class LeftRightWaitNotifyExample {
final static String str = "1";
public static void main(String[] args) throws InterruptedException {
new LeftLegThread(str).start();
Thread.sleep(100);
new RightLegThread(str).start();
}
}
class LeftLegThread extends Thread {
String monitor;
public LeftLegThread(String str) {
monitor = str;
}
@Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
for (int i = 0; i < 2; i++) {
System.out.println("Left ");
monitor.wait();
monitor.notify();
}
}
}
}
class RightLegThread extends Thread {
String monitor;
public RightLegThread(String str) {
monitor = str;
}
@Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
while (true) {
System.out.println("Right ");
monitor.notify();
monitor.wait();
}
}
}
}
当前输出:
Left
Right
Left
Right
Right
为什么Right
只有3,但Left
只有两次。为什么呢?
答案 0 :(得分:5)
您正在monitor
进行同步,所以您应该wait()
在监视器上:
monitor.wait();
现在您正在等待this
,这不是监视器的所有者,因为同步在monitor
上。
请注意,当然notify
也应该在monitor
对象上完成,并且您可能要考虑在中使用notify
/ notifyAll
线程。否则可能会发生一个线程饿死等待丢失通知。使用超时(wait
的重载版本)也可能是捕捉极端情况的好主意。
答案 1 :(得分:0)
原因 - The current thread is not the owner of the object's monitor
。要调用wait()
方法,当前线程必须拥有此对象的监视器。
在您的情况下,您将获得monitor
对象上的监视器而不是当前对象(此对象)。
答案 2 :(得分:0)
您正在尝试锁定监视器对象。但它是锁定线程对象(LeftLegThread,RightLegThread)。实际上它并未锁定同步。
monitor.wait();将会解决。
答案 3 :(得分:0)
public class LeftRightWaitNotifyExample {
final static String str = "1";
public static void main(String[] args) throws InterruptedException {
new LeftLegThread(str).start();
Thread.sleep(1000);
new RightLegThread(str).start();
}
}
class LeftLegThread extends Thread {
String monitor;
public LeftLegThread(String str) {
monitor = str;
}
@Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
while (true) {
System.out.println("Left ");
monitor.wait();
monitor.notify();
Thread.sleep(1000);
}
}
}
}
class RightLegThread extends Thread {
String monitor;
public RightLegThread(String str) {
monitor = str;
}
@Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
while (true) {
System.out.println("Right ");
monitor.notify();
monitor.wait();
Thread.sleep(1000);
}
}
}
}