编辑:

这个问题是关于仅使用Java代码解决问题的。该问题是由SQLLite间接引起的,但是无法通过更改数据库系统或使用SQL代码来解决。我之所以提到SQLLite,是因为否则用户会指向无用的解决方案,这些解决方案实际上会破坏项目施加的要求(已定义的用户界面和行为以及SQLite作为DBMS,因为它可以在没有服务器的情况下运行,并且项目可以自动更正)。

编辑2:
僵局发生在Java端,这不容易看到,我整整调试了一天,然后才意识到,忘记了SQLLite,我需要找到一种方法来使Parking像监视器一样工作,而又不与synchronized冲突僵局



目前我有以下情况:

我有一个简化的Parking类,实际上是一个监视器,客户端从其他线程调用lendVehicle方法。

public class Parking{

    private final long       parkId;
    private final ParkingAPI sqlLayer;
    private final Lock       lock = new ReentrantLock();
    private final Condition  notEmpty = lock.newCondition();

    public Parking( long mparkId, ParkingAPI api){
        sqlLayer = api;
        parkId = mparkId;
    }

    long lendVehicle(){
        lock.lock();
        try{
            while(sqlLayer.countVehicles(parkId) == 0)
                notEmpty.await();

            return sqlLayer.lend(parkId);

        } finally{
            lock.unlock();
        }
    }

    void giveBackVehicle(long vehicleId){
        lock.lock();
        try{
            sqlLayer.giveBack(vehicleId,parkId);
            notEmpty.signal();

        } finally{
            lock.unlock();
        }
    }


当我仅使用原子计数器模拟SQL层时,该类可以正常运行,但是由于应用程序正在使用SQL Lite,因此我必须保护连接免受并发访问(由于SQL Lite,基本上我可以在任何给定时间执行1个查询) 。

当前,代码位于synchronized对象上的DBLayer(所有类均共享)。

class ParkingQuery implements ParkingAPI{

    private final DBLayer connection;

    public SQLLayer(DBLayer db){
        connection = db;
    }

    @Override
    int lend(long parkId){
        synchronized( connection){
            return connection.lendVehicleFromPark(parkId);
        }
    }

    @Override
    int countVehicles(long parkId){
        synchronized( connection){
            return connection.countVehiclesQuery(parkId);
        }
    }

    @Override
    void giveBack(long vehicleId, long parkId){
        synchronized( connection){
            connection.giveBackVehicle(parkId, vehicleId);
        }
    }
}


问题是同步部分,在停车场的显示器上无法很好地发挥作用:实际上会导致死锁。

如何保留停车功能? (无法删除对ParkingQuery的同步,因为如果查询未同步并且不良情况开始发生,SQLite只会爆炸)。

请注意,必须并发访问SQLLite,因为这是一个学校项目。

编辑:
所需的停车行为:
如果用户希望借出车辆而该车辆不可用,则用户必须等待其他人将车辆从借出归还。

最佳答案

这段代码:

long lendVehicle(){
        lock.lock();
        try{
          ...
    }


是错的。您基本上是锁定的,因此它不能保证解锁,因为它在try块之外。尝试更适当地解决该问题。您有一个生产者,这是汽车的回赠,然后您的消费者将汽车借出。因此,您知道您的“车位”只能容纳N辆车(例如,假设10辆)。因此,如果您的缓冲区(车位)已满,则您不想让更多的车退还(请考虑将车停在没有任何停车位的车库中)。

现在,您可以简单地检查回车功能,如果缓冲区已满并且忽略该操作。在借车时,您要确保批次不空。

10-06 06:46