使用Java信号量解决读写问题

3

所以,我们(我和我的同事)面临的是一个经典的并发问题。我们不懈努力,为了让您能够正确地帮助我们,我们提供了一些相关代码。 我们有两个类定义读者和写者,它们都扩展Thread类,并且当然重写run方法,如下所示:

while(!isInterrupted()) {
 try{ 
     Thread.sleep(for some time)
 }catch(InterruptedException e) {}

 database.readLock();
  readersWorking++; //for debugging purposes
 database.readUnlock();
}

作家的run方法基本相同,但我们正在增加writersWorking,也是为了调试目的。
在我们的主方法中,我们创建了20个读者和2个作家。它们都通过构造函数注入获得Database类的一个实例。这是数据库:
class Database {
    Semaphore writeMut = new Semaphore(1);
    Semaphore readMut = new Semaphore(1);
    private int readersWorking = 0;

    public Database() {

    }

    public void readLock() {
        readMut.acquireUninterruptibly();

        if(readersWorking==0) //Am I the first one?
            writeMut.acquireUninterruptibly();
        readersWorking++;

        readMut.release();
    }

    public void writeLock() {
        writeMut.acquireUninterruptibly();
    }

    public void readUnlock() {
        readMut.acquireUninterruptibly();
        readersWorking--;
        if(readersWorking==0) //Am I the last one?
            writeMut.release();
        readMut.release();
    }

    public void writeUnlock() {
        writeMut.release();
    }
}

问题:为什么这段代码会导致读者在写者仍在其中,反之亦然时访问数据库?我们如何阻止这种情况发生?我们的逻辑有什么问题?如果有人知道Java并发方面的好书,请推荐一下。
如果提供的代码不足够,请参考完整代码:http://codepad.org/IJ7e145C

你似乎在不同的类中有几个名为readersWorking和writersWorking的变量。你确定这不会混淆你的调试统计数据吗? - Tudor
2个回答

5
我其实没什么心情彻底分析你的代码(有点懒 :p),但听起来像是java.util.concurrent.locks包几乎正是你所需的。除非你被困在Java 1.4中,否则我强烈建议依靠Java并发工具来完成这个恶心的工作。这样你会更轻松。
至于那本书,看起来很合适

大加1。使用Java并发工具和阅读《Java并发编程实战》一书。 - user949300
哎呀...那个链接一直指向OutputStream吗?它应该是ReadWriteLock,就像EJP发布的一样。对于任何混淆,我已经编辑了它。 - G_H

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接