Similar to the producer and consumer issue in the second kill multi-thread Article 10 producer and consumer issue, reader writers are also a very famous synchronization issue. The reader writer's Problem description is very simple. One writer has many readers who can read files at the same time. However, when writing files, the writer does not allow readers to read files, some readers cannot write files when reading files.
The above is the issue of the reader, similar to the analysis process of the producer and consumer issues. First, let's look at what is "Waiting.
First, the writer will not be able to write files until there are no readers.
2. All readers must wait for the writer to finish writing the file before reading the file.
After finding the "wait" status, check whether there are resources that need mutual access. Since only one writer and the reader can share the read files, there is no resource that requires mutual access according to the question. Similar to the beautiful color output in the previous article, we set the color of the producer output code (for details about the color settings in the console, see VC console color settings). Therefore, a mutex access is required here. Otherwise, the reader thread may have output before the writer thread restores the console color settings. Therefore, the output statement must be mutually exclusive. The output functions of the modified reader and writer are as follows:
// Reader thread output function void readerprintf (char * pszformat ,...) {va_list parglist; va_start (parglist, pszformat); entercriticalsection (& g_cs); vfprintf (stdout, pszformat, parglist); then (& g_cs); va_end (parglist );} // writer thread output function void writerprintf (char * pszstr) {entercriticalsection (& g_cs); setconsolecolor (foreground_green); printf ("% s \ n", pszstr ); setconsolecolor (foreground_red | foreground_green | foreground_blue); leavecriticalsection (& g_cs );}
For variable parameters used by the reader's thread output function, see "using variable parameters in C and C ++".
Solved the problem of mutex output, and then considered how to implement synchronization. You can set a variable to record the number of readers who are reading the file. The first reader who starts to read the file is responsible for disabling the mark that allows the writer to enter, the last reader who stops reading the file is responsible for opening the mark that allows the writer to enter. In this way, the first "wait" situation is solved. The second "Waiting" situation is that when a writer enters, the reader cannot enter, you can use an event to complete this task. All readers must wait for this event, and the writer is responsible for triggering the event and setting the event as not triggered. For details, see comments in the Code:
// Readers and writers # include <stdio. h> # include <process. h> # include <windows. h> // set console output color bool setconsolecolor (word wattributes) {handle hconsole = getstdhandle (std_output_handle); If (hconsole = invalid_handle_value) return false; return setconsoletextattribute (hconsole, wattributes);} const int reader_num = 5; // number of readers // key segment and event critical_section g_cs, g_cs_writer_count; handle g_heventwriter, g_heventnoreader; int g_nreadercount; // reader thread output function (Variable Parameter Function implementation) void readerprintf (char * pszformat ,...) {va_list parglist; va_start (parglist, pszformat); entercriticalsection (& g_cs); vfprintf (stdout, pszformat, parglist); then (& g_cs); va_end (parglist );} // reader thread function unsigned int _ stdcall readerthreadfun (pvoid pm) {readerprintf ("the reader numbered % d enters the waiting... \ n ", getcurrentthreadid (); // wait for the writer to finish waitforsingleobject (g_heventwriter, infinite); // Add entercriticalsection (& g_cs_writer_count); g_nreadercount ++; if (g_nreadercount = 1) resetevent (g_heventnoreader); leavecriticalsection (& g_cs_writer_count); // read the readerprintf file ("the reader with the ID of % d starts to read the file... \ n ", getcurrentthreadid (); sleep (RAND () % 100); // The number of readers decreases, added readerprintf ("the reader with the ID % d stops reading the file \ n", getcurrentthreadid (); // The number of readers reduces entercriticalsection (& g_cs_writer_count); g_nreadercount --; if (g_nreadercount = 0) setevent (g_heventnoreader); leavecriticalsection (& g_cs_writer_count); Return 0;} // The Void writerprintf (char * pszstr) output function of the writer thread) {entercriticalsection (& g_cs); setconsolecolor (foreground_green); printf ("% s \ n", pszstr); setconsolecolor (Response | foreground_green | response); Response (& g_cs );} // writer thread function unsigned int _ stdcall writerthreadfun (pvoid pm) {writerprintf ("writer thread enters waiting... "); // The Reader waiting to read the file is zero waitforsingleobject (g_heventnoreader, infinite); // The tag writer is writing the file resetevent (g_heventwriter ); // write the file writerprintf ("the writer starts to write the file ..... "); sleep (RAND () % 100); writerprintf (" writer end Write File "); // mark the writer end Write File setevent (g_heventwriter); Return 0 ;} int main () {printf ("reader writer question \ n"); printf ("-- by morewindows (http://blog.csdn.net/MoreWindows) -- \ n "); // initialization events and semaphores initializecriticalsection (& g_cs); initializecriticalsection (& g_cs_writer_count); // Manual placement. g_heventwriter = createevent (null, true, true, null) is triggered initially ); g_heventnoreader = createevent (null, false, true, null); g_nreadercount = 0; int I; handle hthread [reader_num + 1]; // start two reader threads for (I = 1; I <= 2; I ++) hthread [I] = (handle) _ beginthreadex (null, 0, readerthreadfun, null, 0, null); // start the writer thread hthread [0] = (handle) _ beginthreadex (null, 0, writerthreadfun, null, 0, null ); sleep (50); // finally start other reader completion processes for (; I <= reader_num; I ++) hthread [I] = (handle) _ beginthreadex (null, 0, readerthreadfun, null, 0, null); waitformultipleobjects (reader_num + 1, hthread, true, infinite); for (I = 0; I <reader_num + 1; I ++) closehandle (hthread [I]); // destroy events and semaphores closehandle (g_heventwriter); closehandle (g_heventnoreader); destroy (& g_cs); deletecriticalsection (& amp; response); Return 0 ;}
The running result is as follows:
The result shows that when a reader reads a file, the writer thread enters the waiting state. When the writer thread is writing files, the reader thread also waits in queue, indicating that the reader and the writer have completed synchronization.
This series lists key segments, events, mutex, and semaphores of Thread Synchronization Methods Through typical thread synchronization issues, and summarizes these four methods. Then, we use two well-known thread synchronization instances-producer consumer issues and reader writer issues to enhance our understanding and application of multi-thread synchronization mutex. We hope that the readers will be able to master the multi-thread questions and get their satisfactory offer.
From the second kill multi-thread Article 10 producer consumer issue to the second kill multi-thread Article 11th reader writer issue, we can conclude that the key to the multi-thread issue is to find all the "Waiting" situations and determine whether mutually exclusive access is required. resources. So how can we identify these problems better, faster, and more comprehensively? Please refer to "second kill multi-thread 12th multi-thread synchronization internal power-PV operation" and "second kill multi-thread 13th multi-thread synchronization internal power-PV operation" to strengthen multi-thread Solution internal tasks of synchronization problems ".
In addition, the reader writer can use the read/write lock srwlock to solve the problem. Please refer to the second kill multi-thread Article 14th reader writer problem following the read/write lock srwlock
Reprinted please indicate the source, original address: http://blog.csdn.net/morewindows/article/details/7596034