0

我正在学习老式的 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 秒安排一次。输出比这快得多,程序不会终止。

4

0 回答 0