gpt4 book ai didi

java - 访问共享资源,锁定解锁或等待通知

转载 作者:行者123 更新时间:2023-11-30 02:44:47 26 4
gpt4 key购买 nike

场景:

多线程从不同来源读取。
共享队列的一个访问点(请参阅尝试编写的 RiderSynchronized 类)
Reader 读取的每一行,都会尝试通过 RiderSynchronized 提供的方法插入到共享队列中。

当共享队列已满时,我必须对准备好的语句运行批处理以插入到 Oracle 中。同时,所有对共享队列的访问都必须被拒绝。

代码:

public class RiderSynchronized {

private ArrayDeque<JSONRecord> queue = new ArrayDeque<>();
private OracleDAO oracleDao;
private long capacity;

public RiderSynchronized(OracleDAO oracleDao, long capacity) {
this.oracleDao = oracleDao;
this.capacity = capacity;
}

public synchronized boolean addRecord(JSONRecord record) {
boolean success = false;
try {
while (queue.size() >= capacity) {
wait();
}

queue.add(record);
if (queue.size() < capacity) {
success = true;
notify(); //notify single Thread
} else {
JSONRecord currentRecord = null;
while ((currentRecord = queue.poll()) != null) {
oracleDao.insertRowParsedIntoBatch(currentRecord);
}
oracleDao.runBatch();
success = true;
notifyAll(); //it could be all Reading Threads are waiting. Notify all

}

} catch (Exception e) {
success = false;
}
return success;
}
}

我必须承认我有点担心一件事。

1) Reader线程可以模糊地使用addRecord吗?他们要等自己吗?或者我是否必须实现一些其他方法来检查运行 addRecord 方法之前的位置?

2)当queue.size <容量时,我决定只通知一个线程,因为恕我直言,此时,任何线程都不应该处于等待状态。我错了吗?我应该通知所有人吗?

2b) “else”语句的确切问题。通知所有是一个好习惯吗?此时,可能所有线程都在等待?

3)最后。我有点担心使用 Lock e Condition Classes 重写所有内容。这是一个更好的决定吗?或者我可以如何运行这个场景?

最佳答案

1) Reader threads can just use addRecord indistinctly? Are They going to wait for themselves? Or Do I have to implement some other method where to check before to run addRecord Method?

您当前代码的问题是,如果由于某种原因 notifyAll不是由理论上应该能够进入 else 的唯一线程调用的阻塞然后你的线程将永远等待

您的代码中的潜在风险是:

  • oracleDao.insertRowParsedIntoBatch(currentRecord)
  • oracleDao.runBatch()

如果这些方法之一抛出异常,则使用您当前的代码 notifyAll永远不会被调用,所以你的线程将永远等待,你至少应该考虑调用 notifyAllfinally阻止以确保它是否发生都会被调用。

<小时/>

2) When queue.size < capacity, I decide to notify just to one thread, because IMHO, at this point, no threads should be in status waiting. Am I wrong? Should I notify All?

您的线程只能等待以防万一 queue.size() >= capacity所以对我来说notify甚至不需要,因为任何线程都不需要这种条件( queue.size() < capacity )。

<小时/>

2b) Exact question for the "else" statement. Is it a good practice to notifyAll? At this point, it could be all threds are waiting?

来自 Effective Java 的第 69 项:

A related issue is whether you should use notify or notifyAll to wake waiting threads. (Recall that notify wakes a single waiting thread, assuming such a thread exists, and notifyAll wakes all waiting threads.) It is often said that you should always use notifyAll. This is reasonable, conservative advice. It will always yield correct results because it guarantees that you’ll wake the threads that need to be awakened. You may wake some other threads, too, but this won’t affect the correctness of your program. These threads will check the condition for which they’re waiting and, finding it false, will continue waiting. As an optimization, you may choose to invoke notify instead of notifyAll if all threads that could be in the wait-set are waiting for the same condition and only one thread at a time can benefit from the condition becoming true. Even if these conditions appear true, there may be cause to use notifyAll in place of notify. Just as placing the wait invocation in a loop protects against accidental or malicious notifications on a publicly accessible object, using notifyAll in place of notify protects against accidental or malicious waits by an unrelated thread. Such waits could otherwise “swallow” a critical notification, leaving its intended recipient waiting indefinitely.

<小时/>

3) Finally. I'm a little concerned to re-write everything using Lock e Condition Classes. Is it a better decision? Or Is it ok how I'm running this scenario?

LockCondition如果您需要内在锁无法提供的功能(例如 tryLock()),那么这些功能很有趣。或者仅唤醒等待给定条件的线程的能力。就您而言,这似乎没有必要,因此您可以保持原样。

关于java - 访问共享资源,锁定解锁或等待通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40512351/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com