How to prevent tiny race condition in a consumer - java

In my applications, two things happen:
Various threads produce jobs.
There is a function (but not 1 constantly running thread) that consumes the jobs. This function is started by the producers, but is locked so that it only runs once.
For example, a job is produced:
addJobToDatabase(...);
triggerPass();
And this is how the consumer function is started:
public void triggerPass() {
// prevent running more than once
if (onceLock.tryLock()) { // onceLock is a ReentrantLock
try {
while (haveJobs()) {
doJobs();
}
} finally {
onceLock.unlock();
}
} else {
log.info("Pass triggered, but already running");
}
}
Now, there is a tiny race condition possible here. If
Thread A has left the while but not yet done onceLock.unlock()
Thread B does onceLock.tryLock() which returns false
...thread B's job is not executed until a later call to triggerPass();
While I doubt it will get me into trouble in practice, can this little gap be closed for correctness?

I think I've worked around it by replacing tryLock() with tryLock(1, TimeUnit.SECONDS). It's not nice though, and not even foolproof if the delay between there are no more jobs and unlock() is longer than 1 second (and who knows what happens in the database).

Unfortunately race condition is unavoidable in this design. Want it to be correct? Why don't you just create something like iterator or queue where the read-modify-write action is the single atomic operation?
public void triggerPass() {
Job job = null;
while ((job = jobIterator.next()) != null) {
doJob(job);
}
}

Related

Is this a proper customized synchronizer?

I had a strong need for a synchronizer similar to a CountDownLatch, but the starting number for the countdown is unknown. To add context, if I'm going through a buffered recordset (say from a text file or a query) and kicking off a runnable for each record, but I don't know how many records there will be... I need a synchronizer that signals when the iteration is complete and all runnables are complete.
This is the synchronizer I came up with... a BufferedLatch. A method is called in the iteration loop for each record incrementing the recordSetSize. At the end of each runnable kicked off for each record, the processedRecordSetSize is incremented. When the iteration through all records is complete (but runnables may still be in queue), the setDownloadComplete() method is called letting the BufferedLatch know the recordSetSize is now fixed. The await() method waits for the iterationComplete variable to be true (recordsetSize is now fixed) and recordsetSize == processedRecordSetSize;
Is this an optimal implementation of this synchronizer? Is there more concurrent opportunity that synchronization is holding back? Although testing seems to work fine, are there any gotcha's I'm overlooking?
import java.util.concurrent.atomic.AtomicInteger;
public final class BufferedLatch {
/** A customized synchronizer built for concurrent iteration processes where the number of objects to be iterated is unknown
* and a runnable will be kicked off for each object, and the await() method will wait for all runnables to be complete
*/
private final AtomicInteger recordsetSize = new AtomicInteger(0);
private final AtomicInteger processedRecordsetSize = new AtomicInteger(0);
private volatile boolean iterationComplete = false;
public int incrementRecordsetSize() throws Exception {
if (iterationComplete) {
throw new Exception("Cannot increase recordsize after download is flagged complete!");
}
else {
return recordsetSize.incrementAndGet();
}
}
public void incrementProcessedRecordSize() {
synchronized(this) {
processedRecordsetSize.incrementAndGet();
if (iterationComplete) {
if (processedRecordsetSize.get() == recordsetSize.get()) {
this.notifyAll();
}
}
}
}
public void setDownloadComplete() {
synchronized(this) {
iterationComplete = true;
}
}
public void await() throws InterruptedException {
while (! (iterationComplete && (processedRecordsetSize.get() == recordsetSize.get()))) {
synchronized(this) {
while (! (iterationComplete && (processedRecordsetSize.get() == recordsetSize.get()))) {
this.wait();
}
}
}
}
}
UPDATE-- NEW CODE
public final class BufferedLatch {
/** A customized synchronizer built for concurrent iteration processes where the number of objects to be iterated is unknown
* and a runnable will be kicked off for each object, and the await() method will wait for all runnables to be complete
*/
private int recordCount = 0;
private int processedRecordCount = 0;
private boolean iterationComplete = false;
public synchronized void incrementRecordCount() throws Exception {
if (iterationComplete) {
throw new Exception("Cannot increase recordCount after download is flagged complete!");
}
else {
recordCount++;
}
}
public synchronized void incrementProcessedRecordCount() {
processedRecordCount++;
if (iterationComplete && recordCount == processedRecordCount) {
this.notifyAll();
}
}
public synchronized void setIterationComplete() {
iterationComplete = true;
if (iterationComplete && recordCount == processedRecordCount) {
this.notifyAll();
}
}
public synchronized void await() throws InterruptedException {
while (! (iterationComplete && (recordCount == processedRecordCount))) {
this.wait();
}
}
}
Probably not. I think conceptually you're onto something here, as it looks like your application needs something more than just a CountDownLatch. However, the implementation seems to have several problems.
First, I note that it looks odd to mix atomics/volatiles AND ordinary object monitor locks (synchronized). While there may be proper uses that mix these different constructs, mixing in this case I believe will lead to errors.
Consider incrementRecordsetSize() which first checks iterationComplete and only if it's false does it increment recordsetSize. The iterationComplete variable is volatile so updates from other threads will be visible. However, the fact that no locking is done here allows TOCTOU race conditions (time-of-check vs time-of-use). The rule seems to be, recordsetSize must not be incremented if iterationComplete is true. Suppose thread T1 comes along and finds iterationComplete to be false, so it decides to increment recordsetSize. Before it does so, another thread T2 comes along and sets iterationComplete to be true. This would allow T1 to do the increment improperly. Worse, before it does so, suppose another thread T3 came along and called incrementProcessedRecordSize(). It would increment processedRecordsetSize and then find iterationComplete true. It further might find that processedRecordsetSize equals recordsetSize and then notify all waiters, who then proceed as if the processing is complete. But it's not, as T1 then proceeds to increment recordsetSize and presumably continues with its processing.
The problem here is that this object's state consists of the fusion of three independent pieces of state -- two int counters and a boolean -- and all three must be read and written atomically. If certain bits of logic attempt to take advantage of individual volatile or atomic properties, it introduces the possibility of race conditions such as the one I described.
I'd suggest rewriting this as a plain object with two plain ints and a boolean (not atomic, not volatile) and just lock around everything. This should certainly clear up the logic and make things easier to understand.
In incrementProcessedRecordSize I note that the condition essentially duplicates the condition in the await method. A simplifying convention is for all updates to notify and have the condition evaluated only by the waiters. This may result in some unnecessary wakeups. If this is a problem, you might consider minimizing the number of notifies, but you need to think about maintainability. If you're not careful, the wait/notify conditions will become spread across the code and will be very hard to reason about. Alternatively, you could refactor the condition into a method and call it from the different places that do waiting and notification.
It looks like await() does a complicated form of double-checked locking. Instead of testing a volatile boolean outside the lock, it tests several separate pieces of information both outside and inside the lock. This seems susceptible to TOCTOU problems (as above) but it might be safe if you can prove the state really latches, that is, that once it becomes true it never returns to false. I'd have to stare at the code for a long time before I'd be able to convince myself it's correct.
On the other hand, what does this buy you? It seems to optimize away just the taking of the lock. If you have a zillion threads that are going to come by after processing is complete, it might be worth it, but it doesn't seem like it. I'd just remove the outer while loop and check the variables within a synchronized block.
Finally, having an object that represents counters and a boolean may very well be sensible for what you're doing, but other things you've said (in the question and in comments) are that some threads are generating a workload (e.g. reading lines from a file) and other threads are retiring that workload. This implies that there is some other data structure like a queue that contains this workload, and you have a producer-consumer problem here. That other structure has to be thread-safe, of course, since multiple threads are interacting over it. But the counters and boolean in this structure need to be updated in lockstep with the updates to the workload structure, otherwise there could be race conditions between checking and updating these separate objects.
It seems to me you could replace the counters in this object with the queue and just put simple locks around everything. The producers would append to the queue until they're done, at which time they set iterationComplete to true which prevents more work from being added. The consumers pull from the queue until iterationComplete is true and the queue is empty, at which point they're done. If they find the queue empty but iterationComplete is false, they know to block while awaiting further work.
I'd say to stick with simple locking and avoid volatiles/atomics until you get the basics correct. If there are bottlenecks in that code, then apply optimizations selectively while preserving the same invariants.

yield() method not working as expected

public class YieldDemo extends Thread{
public static void main(String[] args) {
YieldDemo y1 = new YieldDemo();
YieldDemo y2= new YieldDemo();
y1.start();
y2.start();
}
public void run() {
for(int i=0;i<=5;i++) {
if(i==3) {
Thread.yield();
} else
System.out.println(i+Thread.currentThread().toString());
}
}
}
As per the documentation of yield(), thread-1 should yield and allow thread-2 to process after 3rd loop. However, the output is not as expected. Same thread continues skipping 3rd iteration. After one thread completes the loop, other thread executes with same behaviour. Please explain.
Output:
0Thread[Thread-1,5,main]
1Thread[Thread-1,5,main]
2Thread[Thread-1,5,main]
4Thread[Thread-1,5,main]
5Thread[Thread-1,5,main]
0Thread[Thread-0,5,main]
1Thread[Thread-0,5,main]
2Thread[Thread-0,5,main]
4Thread[Thread-0,5,main]
5Thread[Thread-0,5,main]
The java.lang.Thread.yield() method causes the currently executing thread object to temporarily pause and allow other threads to execute.
NOTE : That other thread can be same thread again. There is no guarantee which thread be chosen by JVM.
As with almost all aspects of Multithreading, even your case isn't guaranteed to behave as expected. Thread.yield() is just like a suggestion to the OS telling - if it is possible, then please execute other threads before this one. Depending on the architecture of your system (number of cores, and other aspects like affinity etc etc) the OS might just ignore your request.
Also, after JDK6U23, the JVM might just change your code to :
public void run() {
for(int i=0;i<=5;i++) {
// 3 is too darn small. and yield() is not necessary
// so let me just iterate 6 times now to improve performance.
System.out.println(i+Thread.currentThread().toString());
}
yield() can totally be ignored (which might be happening in your case. If you are getting the same result over and over again)
Read This article. yield method is to request for a thread to sleep. it may be happen or not.

Proper implementation of producer-consumer scenario and "graceful" termination of thread pool

I am working on my first multi-threaded project and thus have a couple of things that I am unsure of. Details on my setup was on a previous question, in short: I have a thread pool implemented by Executors.newFixedThreadPool(N). One thread is given an action which does a series of queries to local and remote resources and iteratively populates an ArrayBlockingQueue, while the rest of the threads invoke take() method on the queue and process the objects in the queue.
Even though small and supervised tests seem to run OK, I am unsure about how I handle special scenarios such as the beginning (the queue has no items yet), the end (the queue is emptied), and any eventual InterruptedExceptions. I have done some reading here on SO, which then led me to two really nice articles by Goetz and Kabutz. The consensus seems to be that one should not ignore these exceptions. However I am unsure how the examples supplied relates to my situation, I have not invoked thread.interrupt() anywhere in my code... Speaking of which, I'm getting unsure if I should have done so...
To sum it up, given the code below, how do I best handle the special cases, such as termination criteria and the InterrruptedExceptions? Hope the questions make sense, otherwise I'll do my best to describe it further.
Thanks in advance,
edit: I have been working on the implementation for a while now, and I have come across a new hiccup so I figured I'd update the situation. I have had the misfortune of coming across ConcurrentModificationException which was most likely due to incomplete shutdown/termination of the thread pool. As soon as I figured out I could use isTerminated() I tried that, then I got a IllegalMonitorStateException due to an unsynchronized wait(). The current state of the code is below:
I have followed some of the advices from #Jonathan's answer, however I don't think his proposal works quite like what I need/want. The background story is the same as I have mentioned above, and relevant bits of code are as follows:
Class holding/managing the pool, and submission of runnables:
public void serve() {
try {
this.started = true;
pool.execute(new QueryingAction(pcqs));
for(;;){
PathwayImpl p = bq.take();
if (p.getId().equals("0")){
System.out.println("--DEBUG: Termination criteria found, shutdown initiated..");
pool.shutdown();
// give 3 minutes per item in queue to finish up
pool.awaitTermination(3 * bq.size(), TimeUnit.MINUTES);
break;
}
int sortMethod = AnalysisParameters.getInstance().getSort_method();
pool.submit(new AnalysisAction(p));
}
} catch (Exception ex) {
ex.printStackTrace();
System.err.println("Unexpected error in core analysis, terminating execution!");
System.exit(0);
}finally{ pool.shutdown(); }
}
public boolean isDone(){
if(this.started)
return pool.isTerminated();
else
return false;
}
Elements are added to the queue by the following code on located in a separate class:
this.queue.offer(path, offer_wait, TimeUnit.MINUTES);
... motivation behind offer() instead of take() is as Jonathan mentioned. Unforeseen blocks are annoying and hard to figure out as my analysis take a long time as it is. So I need to know relatively quick if the fails due to a bad block, or if it's just crunching numbers...
and finally; here's the code in my test class where I check the interaction between the "concurrency service" (named cs here) and the rest of the objects to be analyzed:
cs.serve();
synchronized (this) {
while(!cs.isDone())
this.wait(5000);
}
ReportGenerator rg = new ReportGenerator();
rg.doReports();
I realize that this has been a VERY long question but I tried to be detailed and specific. Hopefully it won't be too much of a drag, and I apologize in case it is...
Instead of using take, which blocks, use something more like this:
PathwayImpl p = null;
synchronized (bq) {
try {
while (bq.isEmpty() && !stopSignal) {
bq.wait(3000); // Wait up to 3 seconds and check again
}
if (!stopSignal) {
p = bq.poll();
}
}
catch (InterruptedException ie) {
// Broke us out of waiting, loop around to test the stopSignal again
}
}
This assumes that the block is enclosed in some sort of while (!stopSignal) {...}.
Then, in the code that adds to the queue, do this:
synchronized (bq) {
bq.add(item);
bq.notify();
}
As for InterruptedExceptions, they are good for signaling the thread to test the stop signal immediately, instead of waiting until the next timeout-and-test. I suggest just testing your stop signal again, and possibly logging the exception.
I use them when signaling a panic, versus a normal shutdown, but it is rare that such a situation is necessary.

Is there a faster version of SynchronousQueue for synchronizing only 2 threads?

I have a case in my application where I need to launch an asynchronous task and then block for it to complete. (Yes, yes, I know that it not optimal, but it's an artifact of the libraries we're using.)
Specifically, I need to call a function and pass a callback object, and the actual callback will occur on a separate thread. But I want to wait for the callback to occur, essentially building a synchronous mechanism on top of an asynchronous one.
So my code looks something like this:
private static class MethodCallback implements RpcCallback<Message> {
private Message message = null;
private boolean done = false;
private long started = System.currentTimeMillis();
public synchronized void run(Message parameter) {
long elapsed = System.currentTimeMillis() - started;
log.debug("Got callback after {} millis", elapsed);
this.message = parameter;
this.done = true;
notifyAll();
}
public synchronized void await() throws ServiceException {
while(!done && (System.currentTimeMillis() - started < MAX_WAIT_MILLIS)) {
try {
long remaining = (started + MAX_WAIT_MILLIS) - System.currentTimeMillis();
if(remaining <= 0) {
remaining = 1;
}
wait(remaining);
} catch(InterruptedException e) {
break;
}
}
if(!done) {
String msg = String.format("Timeout: No response from async process");
log.warn(msg);
throw new ServiceException(msg);
}
}
public Message get() {
return message;
}
}
public Message getMessageFromAsyncProcess() {
MethodCallback callback = new MethodCallback();
channel.doAsyncThing(callback);
callback.await();
Message result = callback.get();
if(result == null) {
throw new ServiceException("Error: async process did not produce a result");
}
return result;
}
Now, this code works perfectly well, and the application performs acceptably quickly. But profiling has determined that MessageCallback.run is a performance bottleneck, presumably due to synchronization.
So as an experiment, I modified the code to use a SynchronousQueue instead, expecting that this would improve the performance. But to my surprise it made it run about twice as slowly (approximately 15ms per call on average versus approximately 7ms per call for the do-it-the-hard-way version).
I could presumably hack up an alternative mechanism using either a Semaphore or something like AtomicBoolean, but should I expect either of those would perform any better?
Given that I only have two threads, and I simply want one of them to wait until the other has produced a single result, is there any mechanism that will be better than what I'm doing now?
My guess is you are using a Windows system which has a clock resolution of about 15 ms. I suggest you try using System.nanoTime() for more accurate timings.
The most obvious solution is to use an executor service which would only take a few lines of code as is designed to do exactly what you trying to achieve.
You should be able to switch between threads passing a task back and forth, in about 1 - 8 us (micro-seconds) Even under load, you best timings should be about this time.
Note: your wait() method will not wake up until it can obtain a lock (after run() completes) This probably isn't what you intended.
Looking at the code, I can see nothing obvious that would make it a bottleneck.
If you are getting times like 7ms and 15ms for this, I suspect that the root cause is that you have significantly more active (runnable) threads than physical processors. If this is the case, then the longish delays are due to waiting for a processor to become available to run a thread that has become runnable. You might be able to improve the average delays by reducing the number of threads, but this might also reduce overall throughput.
Incidentally, I think that your custom synchronization code could be replaced with use of FutureTask, though I don't expect this would reduce average call times.

killing an infinite loop in java

I am using a third-party library to process a large number of data sets. The process very occasionally goes into an infinite loop (or is blocked - don't know why and can't get into the code). I'd like to kill this after a set time and continue to the next case. A simple example is:
for (Object data : dataList) {
Object result = TheirLibrary.processData(data);
store(result);
}
processData normally takes 1 second max. I'd like to set a timer which kills processData() after , say, 10 seconds
EDIT
I would appreciate a code snippet (I am not practiced in using Threads). The Executor approach looks useful but I don't quite know how to start. Also the pseudocode for the more conventional approach is too general for me to code.
#Steven Schlansker - suggests that unless the thirdparty app anticipates the interrupt it won't work. Again detail and examples would be appreciated
EDIT
I got the precise solution I was wanting from my colleagues Sam Adams, which I am appending as an answer. It has more detail than the other answers, but I will give them both a vote. I'll mark Sam's as the approved answer
One of the ExecutorService.invokeAll(...) methods takes a timeout argument. Create a single Callable that calls the library, and wrap it in a List as an argument to that method. The Future returned indicate how it went.
(Note: untested by me)
Put the call to the library in another thread and kill this thread after a timeout. That way you could also proces multiple objects at the same time if they are not dependant to each other.
EDIT: Democode request
This is pseudo code so you have to improve and extend it. Also error checking weather a call was succesful or not will be of help.
for (Object data : dataList) {
Thread t = new LibThread(data);
// store the thread somewhere with an id
// tid and starting time tstart
// threads
t.start();
}
while(!all threads finished)
{
for (Thread t : threads)
{
// get start time of thread
// and check the timeout
if (runtime > timeout)
{
t.stop();
}
}
}
class LibThread extends Thread {
Object data;
public TextThread(Object data)
{
this.data = data;
}
public void processData()
{
Object result = TheirLibrary.processData(data);
store(result);
}
}
Sam Adams sent me the following answer, which is my accepted one
Thread thread = new Thread(myRunnableCode);
thread.start();
thread.join(timeoutMs);
if (thread.isAlive()) {
thread.interrupt();
}
and myRunnableCode regularly checks Thread.isInterrupted(), and exits cleanly if this returns true.
Alternatively you can do:
Thread thread = new Thread(myRunnableCode);
thread.start();
thread.join(timeoutMs);
if (thread.isAlive()) {
thread.stop();
}
But this method has been deprecated since it is DANGEROUS.
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#stop()
"This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior."
I've implemented the second and it does what I want at present.

Categories

Resources