以下是代码:
public class LogService {
private final BlockingQueue<String> queue;
private final LoggerThread loggerThread;
private final PrintWriter writer;
@GuardedBy("this") private boolean isShutdown;
@GuardedBy("this") private int reservations; // <-- counter
public void start() { loggerThread.start(); }
public void stop() {
synchronized (this) { isShutdown = true; }
loggerThread.interrupt();
}
public void log(String msg) throws InterruptedException {
synchronized (this) {
if (isShutdown)
throw new IllegalStateException(...);
++reservations;
}
queue.put(msg);
}
private class LoggerThread extends Thread {
public void run() {
try {
while (true) {
try {
synchronized (LogService.this) {
if (isShutdown && reservations == 0)
break;
}
String msg = queue.take();
synchronized (LogService.this) {
--reservations;
}
writer.println(msg);
} catch (InterruptedException e) { /* retry */ }
}
} finally {
writer.close();
}
}
}
}
它是 Java Concurrency in Practice 这本书的摘录,我想到的可能是计数器reservations
是不必要的,因为我们可以简单地使用{{ 1}}获取queue.size()
中的元素数量。
我是对的吗?
答案 0 :(得分:5)
不,这会造成实际的死锁。
如果您想以并行方式使用put
,则需要同步take
和size
。但take
正在屏蔽,您现在可以在与take
调用相同的对象上同步阻止put
调用。 take
只有put
才能使用put
。在take
放弃锁定之前, for(i=0;i<=50;i++)
if(i%10==4)
{
printf("%d",i);
}
无法放置。那是一个僵局。