Subj : Re: pthreads:same thread taking the control To : comp.programming.threads From : David Butenhof Date : Mon Sep 26 2005 12:54 pm prasi wrote: > hi, > all > I am new to threads,now I am learning pthreads.I have implemented a > simple threaded program to check out condition variables in threads. > > > The code is as follows > > #include > #include > > /*this program creates two threads one thread will read the data from > the keyboard stores in the buffer and another will read from the buffer > and displays on the monitor.I am using pthread_cond_wait() and signal() > for synchronization*/ > > //mutex to handle the shared data between read and write > > pthread_mutex_t shared_data; > //condition variable > pthread_cond_t got_data; > char *buffer; > pthread_t thread_id[10]; > > int num_bytes_written=0; > void * read_sh_write_mon(void *arg) > { > > char str[100]; > //bytes_to_read=*(int *)arg; > while(1) > { > pthread_mutex_lock(&shared_data); > printf("write: num of bytes written=%d\n",num_bytes_written); > pthread_cond_wait(&got_data,&shared_data); > printf("write mon\n"); > write(1,buffer,num_bytes_written); > pthread_mutex_unlock(&shared_data); > } > } > > void * read_kb_write_sh(void *arg) > { > int bytes; > while(1) > { > pthread_mutex_lock(&shared_data); > printf("read\n"); > bytes=read(0,buffer,1024); > num_bytes_written=bytes; > pthread_cond_signal(&got_data); > printf("signal to write:num of bytes:%d\n",num_bytes_written); > pthread_mutex_unlock(&shared_data); > printf("unlock\n"); > } > > } > > int main() > { > > buffer=(char *)malloc(1024); > pthread_mutex_init(&shared_data, NULL); > pthread_cond_init (&got_data, NULL); > pthread_create(&thread_id[0],NULL,read_sh_write_mon,NULL); > pthread_create(&thread_id[1],NULL,read_kb_write_sh,NULL); > printf("%d:\n",getpid()); > > for(;;) { > > printf( "server is running\n" ); > > pthread_yield(); > sleep(8); > } > > > > } > > > > " The problem is , the control is not transferring to the write thread > ,the read thread is always getting the control and simply wait for > accepting the data from the keyboard" > > Please mail me the reason if anybody knows. Your first problem is that there's no real synchronization between threads. You have simple "mutual exclusion" through the mutex; but, as you've observed, it's quite possible that the read thread will re-acquire the mutex immediately rather than waiting for the write thread. There's no reason it shouldn't, as you haven't told the system anything about the interaction. In the absence of any better data it's always more efficient for the currently running thread to continue running than to switch it out and switch in another! One solution is to use num_bytes_written ("num_bytes_read" might be a better name ;-) ) as a predicate -- the expression that defines your shared data state. The read thread can only proceed when num_bytes_written is 0; and the write thread would set num_bytes_written to 0 after the write finishes. To do that you'd add a second condition variable (e.g., "data_done"), which the write thread would signal (when it finishes), and on which the read thread would wait (before reading a new buffer). Your second problem is that your use of condition variables leaves your code vulnerable to race conditions. A condition variable isn't a monitor, because it can't know anything about the state of your data or what that state means. It's just a signalling mechanism between threads. You should always wait for a condition variable in a loop, based on some predicate condition of your shared data. For example, you might use num_bytes_written, if your write thread sets that value to 0 after the write finishes. For example, in the write thread, pthread_mutex_lock (&shared_data); while (num_bytes_written == 0) pthread_cond_wait (&dot_data, &shared_data); write(...); num_bytes_written = 0; pthread_mutex_unlock (&shared_data); The third problem (ultimately more severe and harder to fix than the others, but with no direct impact on your immediate symptom) is that you've written a "threaded sequential program". You have two threads, yes; but they cannot EVER do anything simultaneously, because they both operate entirely with exclusive access to a single shared resource (buffer). You've essentially written a serial/sequential program and SLOWED IT DOWN AND COMPLICATED IT by adding threads. (If this "exclusive round robin" behavior is really what you want, get rid of the threads; the program will work better, and be a lot easier to follow.) If you'd rather make it parallel, there are many ways to fix the problem with more careful design, depending on your actual intentions for the real program of which this might serve as a prototype. At the most trivial level, for example, you might switch "buffer" to a multi-buffering set, or even a queue, so that your read and write threads can operate independently on DIFFERENT buffers at the same time, and then coordinate. (That is, the read thread would read a PRIVATE buffer of input, and then write the shared "buffer" pointer, signalling the write thread that input was ready. The write thread, when it finished a write, would wait for a new input buffer, copy the pointer and clear the shared pointer, write the data, free the buffer, and wait for a new input buffer.) With a little more sophistication the write thread can "recycle" the buffer rather than freeing it and making the read thread allocate a new one. You can make the read thread add buffers to a queue so that it can process input as quickly as it comes even if the write thread gets delayed -- if it queues a second input buffer while the write thread is working, it'll just catch up later. (Though there are certainly applications where that model might not be appropriate.) -- Dave Butenhof, David.Butenhof@hp.com HP Utility Pricing software, POSIX thread consultant Manageability Solutions Lab (MSL), Hewlett-Packard Company 110 Spit Brook Road, ZK2/3-Q18, Nashua, NH 03062 .