I'm looking for a concurrency object that can assist in the following use case:
- threads/entities: 1 publisher (unique), 0-many readers
- publisher frequently / erratically updates a data structure, needs to do so quickly and with minimal latency
- each reader has read access to the data structure (either through something that doesn't allow writes, or because the reader implicitly promises not to change data)
- each reader is willing to try repeatedly to access the data structure, as long as it can detect when the publisher has come and changed it, because it knows it will eventually get enough time to read what it needs.
Any suggestions? I can use a ReentrantReadWriteLock
but am somewhat concerned about blocking the publisher. I would rather have the publisher be able to ruin a reader's chance to read, than to have a reader be able to hold up the publisher.
publisher thread:
PublisherSignal ps = new PublisherSignal();
publishToAllReaders(ps.getReaderSignal());
...
while (inLoop())
{
ps.beginEdit();
data.setSomething(someComputation());
data.setSomethingElse(someOtherComputation());
ps.endEdit();
doOtherStuff();
}
reader thread:
PublisherSignal.Reader rs = acquireSignalFromPublisher();
...
while (inLoop())
{
readDataWhenWeGetAChance();
doOtherStuff();
}
...
public readDataWhenWeGetAChance()
{
while (true)
{
rs.beginRead();
useData(data.getSomething(), data.getSomethingElse());
if (rs.endRead())
{
// we get here if the publisher hasn't done a beginEdit()
// during our read.
break;
}
// darn, we have to try again.
// might as well yield thread if appropriate
rs.waitToRead();
}
}
edit: at a higher level, what I am trying to do is have the publisher change data several thousand times a second, and then have readers display the latest update at a much slower rate (5-10 times a second). I would use a ConcurrentLinkedQueue to publish the fact that an update has occurred, except that (a) there may be hundreds of updates on the same item, which I would like to coalesce, because having to copy tons of data repeatedly seems like a waste is a performance problem, and (b) having multiple readers seems to rule out a queue... I suppose I could have one master proxy reader and have it notify each of the real readers.