Subj : Re: How to ensure that a thread runs while another is doing I/O To : comp.programming.threads From : Anant Padmanath Mudambi Date : Mon Jan 10 2005 09:39 am Hi, I see the problem with spurious wakeup of thread_1, but what I wanted to know was something else. If thread_1 is doing I/O and thread_2 is runnable, how can we ensure that thread_2 executes while thread_1 is waiting for the I/O to finish. My test code shows these 2 outcomes: 1] thread_1 starts file write thread_2 starts CPU bound work thread_2 finishes CPU bound work thread_1 finishes file write OR 2] thread_1 starts file write thread_1 finishes file write thread_2 starts CPU bound work thread_2 finishes CPU bound work I want to know if we can guarantee outcome 1] all the time. Thank you, Anant. On Sun, 9 Jan 2005, Joseph Seigh wrote: > On Sun, 9 Jan 2005 19:56:32 -0500, Anant Padmanath Mudambi wrote: > > > Hi all, > > Consider this psuedo code: > > > > M1,M2 : mutexes C: condition variable > > > > thread_1 > > { > > mutex_lock(M1); > > mutex_lock(M2); > > create thread_2; > > cond_wait(C, M1); > > mutex_unlock(M1); > > mutex_unlock(M2); > > big write to a file on disk; > > join(thread_2); > > } > > > > thread_2 > > { > > mutex_lock(M1); > > CPU-bound work #1; > > mutex_unlock(M1); > > cond_signal(C); > > mutex_lock(M2); > > CPU-bound work #2; > > } > > > > By putting printf()s in this code I saw that after thread_2 signals C, > > sometimes the "CPU-bound work #2" executes while thread_1 is waiting for > > the file write to finish and sometimes it executes AFTER the whole file > > write finishes. > > > > How can I ensure that thread_2 always continues to execute as soon as > > possible without waiting for the whole file write in thread_1 to finish? > > Assume these are the only 2 user threads on the system. > > > > The problem you are likely seeing is that you are using the condition > variable incorrectly. You need to use it in conjunction with a testable > data condition so you can correctly deal with spurious wakeups, which is > what you're probably seeing with thread 1 starting i/o without actually > being explicitly signaled. For instance, use a "done" flag to indicate the > work is done. so your thread 1 wait becomes > > while (!done) > cond_wait(C, M1); > > and your thread 2 signal becomes > > done = true; > mutex_unlock(M1); > cond_signal(C); > > Your signal can be with or without the lock held after you've set the flag > but setting the flag must be with the lock held. > > Also, doing a condition wait on the not most recently acquired lock is > a BAD habit. Thread 1 is acquiring lock M2 while M1 held and then > reacquiring M1 on exit from wait while M2 is held. You don't have > a consistent lock hierarchy. If any other thread tried to acquire > both locks you could get deadlock. Get out of that habit unless you > want to learn how to debug deadlocks. So switch the order of the first > two statements in thread 1. > > - > Joe Seigh > .