我正在学习老式的 Java 同步机制,并偶然发现了一些问题。代码在GitHub上可用。
考虑以下测试示例。
从 main 方法中,我们构造了一个车库Platform对象,由一个 char 矩阵表示。已经停放了两辆汽车(用x表示)和一辆挡在路上的车辆(用v表示)。汽车从位置(1,0)进入车库并驶过,如红色所示,左右寻找可用停车位。
从 main 方法创建三十个车辆(线程)并start()调用该方法。如果前面有一辆车挡住了他们的去路,他们必须调用wait()共享Platform.lock对象。
该类Observer负责将车库的当前状态打印到控制台。
出现问题的地方是MysteryVehicle线程,它唯一的工作是移除障碍物(用v表示)并让汽车有条不紊地通过。似乎这个对象永远不会获得锁的监视器。
主班
package garage;
import garage.model.*;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
Platform platform = new Platform();
Vehicle.platform = platform;
platform.print();
Vehicle[] vehicles = new Vehicle[30];
for (int i = 0; i < 30; i++) {
vehicles[i] = new Vehicle();
}
for (int i = 0; i < 30; i++) {
vehicles[i].start();
}
Observer observer = new Observer();
observer.platform = platform;
observer.setDaemon(true);
observer.start();
MysteryVehicle mysteryVehicle = new MysteryVehicle();
mysteryVehicle.start();
try {
mysteryVehicle.join();
} catch (Exception exception) {
exception.printStackTrace();
}
try {
for (int i = 0; i < 30; i++)
vehicles[i].join();
} catch (Exception exception) {
exception.printStackTrace();
}
platform.print();
System.out.println("END");
System.out.println(platform.flag); // checks whether wait() was called anytime
}
public static void main(String[] args) {
launch(args);
}
}
平台类
package garage.model;
public class Platform {
public boolean flag = false; // indicades whether wait() was called anytime
public char[][] fields = new char[10][8];
public static final Object lock = new Object();
public Platform() {
for (int i = 0; i < 10; i++)
for (int j = 0; j < 8; j++)
fields[i][j] = '.';
fields[1][0] = fields[2][0] = 'x'; // already parked cars
fields[4][1] = 'v'; // obstacle
}
public void print() {
synchronized (lock) {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(fields[i][j]);
}
System.out.println();
}
System.out.println();
}
}
}
车辆等级
package garage.model;
public class Vehicle extends Thread {
int x = 1;
int y = 0;
private int block = 1;
public static Platform platform;
public boolean moving = true;
public void run() {
y++; // entrance
while (moving) {
if (block == 1) {
while (moving && platform.fields[x + 1][y] == 'v')
try {
synchronized (Platform.lock) {
Platform.lock.wait();
platform.flag = true;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (Platform.lock) {
x++;
Platform.lock.notifyAll();
yield(); // suggest another vehicle should get processor time
}
// looking left and right for an available spot
if (platform.fields[x][0] != 'x' && platform.fields[x][0] != '*') {
platform.fields[x][0] = '*'; // park
moving = false;
} else if (x < 8 && platform.fields[x][3] != 'x' && platform.fields[x][3] != '*'
&& platform.fields[x][2] != 'v') {
platform.fields[x][3] = '*';// park
moving = false;
}
// checking if we reached the end
if (moving && x == 9) {
block = 2;
move(); // transfer to the second block of the garage
}
} // end block 1
if (block == 2) {
// looking left and right for an available spot
if (platform.fields[x][7] != 'x' && platform.fields[x][7] != '*') {
platform.fields[x][7] = '*'; // park
moving = false;
} else if (x < 8 && platform.fields[x][4] != 'x' && platform.fields[x][4] != '*'
&& platform.fields[x][5] != 'v') {
platform.fields[x][4] = '*'; // park
moving = false;
}
while (moving && platform.fields[x - 1][y] == 'v')
try {
synchronized (Platform.lock) {
Platform.lock.wait(); // waiting for the mystery vehicle to disappear
platform.flag = true;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
if (moving) {
synchronized (Platform.lock) {
x--;
Platform.lock.notifyAll();
yield();
}
}
if (x == 1) {
y++;
moving = false;
}
} // end block 2
} // end moving
}
private void move() {
while (y != 6) {
if (y + 1 == 'v')
try {
synchronized (Platform.lock) {
platform.flag = true;
Platform.lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (Platform.lock) {
y++;
Platform.lock.notifyAll();
yield();
}
}
}
}
观察者类
package garage.model;
public class Observer extends Thread {
public Platform platform;
{
setPriority(MIN_PRIORITY);
}
@Override
public void run() {
while (true) {
synchronized (Platform.lock) {
try {
sleep(2000);
platform.print();
yield();
} catch (InterruptedException exception) {
exception.printStackTrace();
} finally {
Platform.lock.notifyAll();
}
}
}
}
}
神秘车辆类
package garage.model;
public class MysteryVehicle extends Vehicle {
{
setPriority(MAX_PRIORITY);
}
@Override
public void run() {
synchronized (Platform.lock) {
System.out.println("And the vehicle disappears!");
platform.fields[4][1] = '.';
}
}
}
一段时间后,Observer产生以下永远不会改变的输出。似乎 MysteryVehicle 从来没有得到处理器时间,所有的汽车都被卡住了。
我在这里想念什么?
更新:
由于yield()不释放锁,我尝试使用wait()- 并得到了IllegalMonitorStateException,即使wait()在同一个锁上同步的块内!
我尝试更改Observer为 a TimerTask,由 aTimer每 5 秒安排一次。输出比这快得多,程序不会终止。

