说有一个图书馆。人们可以借书和归还书籍。每本书都有一个或多个副本。
让我们假设:
1.如果一个人带着书籍来到图书馆,他将不会在没有所有书籍的情况下离开图书馆。
2.在某些借款人的名单上,有可能是图书馆没有至少一份副本的书籍。
我们同意借款人由线程代表。
我只能想到实现它的一个选项:
public synchronized void borrowBooks(final ArrayList<Item> booksList)
{
try {
while (!areBooksPresent(booksList)) {
this.wait();
}
} catch (InterruptedException e) {}
for (Book book : booksList) {
Book libraryBook = findBook(book);
/* Decrement the book's amount in the library */
libraryBook.decAmount();
}
}
public synchronized void returnBooks(final ArrayList<Item> booksList)
{
for (Book book : booksList) {
Book libraryBook = findBook(book);
/* increment the book's amount in the library */
libraryBook.incAmount();
/* Notify to all awaiting threads that the monitor is freed */
this.notifyAll();
}
}
正如您所看到的,当一个线程开始借用他的书时,整个库都被锁定,没有其他线程可以同时借用。我们还保证在借用书籍的for
循环中,不可能出现一本书。
主要问题是当我们每次线程借书时锁定整个库时,我们就失去了多线程程序的全部意义。
其他替代方案似乎导致死锁。
对于更安全且有活力的更多并发解决方案,您有什么建议吗?
答案 0 :(得分:1)
为每本书保留一个结构,允许线程阻止,直到返回特定的书。
让每个借款人等待至少一本所需的书籍。当它醒来时,请检查它所需的所有书籍是否可用。如果是这样的话,它应该全部带走并离开。如果没有,它应该选择一本不可用的书籍并等待它。
然而,这可能导致一些借款人永远等待。为避免这种情况,请使用特殊优先级算法。在抵达顺序中保留借款人的队列。把新的借款人放在后面。然后简单地实施一条规则 - 如果借款人需要任何书籍,只有借款人可以接受。这将留下一个你需要处理的特殊情况:借款人不是借款人,所需的所有书籍都可以使用,但由于借款人需要其中一本书,因此无法接受。在这种情况下,有一个特殊的&#34;借款人已离开&#34;借款人可以等待的事件。当借款人获得所有账簿时,检查它是否是借款人,如果是,则取消阻止等待该事件的所有线程。
任何给定的借款人在任何时候都有一些有限数量的借款人。这个数字不能增加。它会减少,因为你前面的一个借款人(头一个)具有绝对的优先权,并且每本书最终都会被退回。没有借款人在等待其他书籍时曾经拿过一本书。所以这应该是无死锁的。