# Include <windows. h> # include <fstream> // different from textbooks # include <iostream> // different from textbooks # include <string> # include <conio. h> using namespace STD; // defines some constants; // The maximum number of critical sections allowed by this program; # define max_buffer_num10 // The multiplication factor in seconds to milliseconds; # define inte_per_sec 1000 // The total number of Production and Consumption threads allowed by this program; # define max_thread_num 64 // defines a structure, record the parameter struct threadinfo {intserial; // The thread serial number charentity; // P or cdoubledelay; // specifies the thread delay intthread_request [max_thread_num]; // thread Request queue int N_request; // number of requests}; // global variable definition // critical area object declaration, used to manage mutually exclusive access to the buffer zone; critical_sectionpc_critical [max_buffer_num]; int buffer_critical [max_buffer_num]; // buffer declaration, used to store products; handle h_thread [max_thread_num]; // array used to store each thread handle; threadinfothread_info [max_thread_num]; // thread information array; handleempty_semaphore; // a semaphore; handleh_mutex; // A mutex; dwordn_thread = 0; // the actual number of threads; dwordn_buffer_or_critical; // the actual number of buffer or critical zone; handleh_semaphore [max_thread _ Num]; // The semaphore that the producer allows the consumer to start consuming; // The Void produce (void * P) declared for production consumption and helper functions; void consume (void * P ); bool ifinotherrequest (INT); int findproducepositon (); int findbufferposition (INT); int main (void) {// declare the required variable; dwordwait_for_all; ifstreaminfile; // initialize the buffer; for (INT I = 0; I <max_buffer_num; I ++) buffer_critical [I] =-1; // initialize the Request queue for each thread; For (Int J = 0; j <max_thread_num; j ++) {for (int K = 0; k <max_thread_num; k ++) thread_info [J]. thread_request [K] =-1; thread_info [J]. n_request = 0;} // initialize the critical section; For (INT I = 0; I <max_buffer_num; I ++) initializecriticalsection (& pc_critical [I]); // open the input file, extracts information such as threads in the specified format. infile. open ("test.txt"); // obtain the actual number of buffers from the file; infile> n_buffer_or_critical; n_buffer_or_critical = infile. get (); printf ("input file: \ n"); // The number of buffers obtained by ECHO; printf ("% d \ n", (INT) n_buffer_or_critical); // extract information of each thread to the corresponding data structure; while (infile) {infile> thread_info [n_thread ]. Serial; infile> thread_info [n_thread]. entity; infile> thread_info [n_thread]. Delay; char C; infile. Get (c); While (C! = '\ N '&&! Infile. EOF () {infile> thread_info [n_thread]. thread_request [thread_info [n_thread]. n_request ++]; infile. get (c) ;}n_thread ++;} // The thread information obtained by ECHO, which is easy to confirm. For (Int J = 0; j <(INT) n_thread; j ++) {int temp_serial = thread_info [J]. serial; char temp_entity = thread_info [J]. entity; double temp_delay = thread_info [J]. delay; printf ("\ n thread % 2D % C % F", temp_serial, temp_entity, temp_delay); int temp_request = thread_info [J]. N _ Request; For (int K = 0; k <temp_request; k ++) printf ("% d", thread_info [J]. thread_request [k]); cout <Endl;} printf ("\ n"); // create several necessary semaphores in the simulation process: empty_semaphore = createsemaphore (null, n_buffer_or_critical, n_buffer_or_critical, null); h_mutex = createmutex (null, false, null ); // The following cycle uses the thread ID to name the synchronous semaphores used for product read/write of the corresponding production thread. For (Int J = 0; j <(INT) n_thread; j ++) {STD: String Lp = "semaphore_for_produce _"; int temp = J; while (temp) {ch Ar c = (char) (TEMP % 10); LP + = C; temp/= 10;} h_semaphore [J + 1] = createsemaphore (null, 0, n_thread, null) ;}// create producer and consumer threads; For (INT I = 0; I <(INT) n_thread; I ++) {If (thread_info [I]. entity = 'P') h_thread [I] = createthread (null, 0, (lpthread_start_routine) (produce), & (thread_info [I]), 0, null ); elseh_thread [I] = createthread (null, 0, (lpthread_start_routine) (consume), & (thread_info [I]), 0, null );} // The main program waits for the action of each thread to end; wait_for_all = Wai Tformultipleobjects (n_thread, h_thread, true,-1); printf ("\ n all producers and consumers have completed their work. \ n "); printf (" press any key to return! \ N "); _ getch (); Return 0 ;}// check whether any consumption request to the same product is not executed; bool ifinotherrequest (INT req) {for (INT I = 0; I <n_thread; I ++) for (Int J = 0; j <thread_info [I]. n_request; j ++) if (thread_info [I]. thread_request [J] = req) return true; return false;} // locate the empty buffer location currently available for product production; intfindproduceposition () {int emptyposition; for (INT I = 0; I <n_buffer_or_critical; I ++) if (buffer_critical [I] =-1) {emptyposition = I; // use the following special value to indicate that the buffer is being written. buffer_c Ritical [I] =-2; break;} return emptyposition;} // locate the position of the product to be produced by the current producer; int findbufferposition (INT propos) {int temppos; for (INT I = 0; I <n_buffer_or_critical; I ++) if (buffer_critical [I] = propos) {temppos = I; break;} return temppos ;} // producer process void produce (void * P) {// local variable Declaration; dwordwait_for_semaphore, wait_for_mutex, m_delay; intm_serial; // obtain the thread information; m_serial = (threadinfo *) (p)-> serial; m_delay = (DWORD) (threadinfo *) (P )-> Delay * inte_per_sec); sleep (m_delay); // start the request to produce printf ("producer % 2D sends the production request signal. \ n ", m_serial); // confirm that the free buffer zone is available for production, and reduce the number of empty locations by 1; for synchronization between producers and consumers; wait_for_semaphore = waitforsingleobject (empty_semaphore, -1); // mutually exclusive access to the next blank critical section that can be used for production, to achieve mutually exclusive write and write; wait_for_mutex = waitforsingleobject (h_mutex,-1); int producepos = findproduceposition (); releasemutex (h_mutex); // After the producer obtains its own null position and marks it, the following write operations can be performed concurrently among the producers; // In the core production step, the program uses the producer ID as the product number to facilitate consumer recognition. Don't; printf ("producer % 2D starts producing products in buffer % 2D. \ n ", m_serial, producepos); buffer_critical [producepos] = m_serial; printf (" producer % 2D finished production process: \ n ", m_serial ); printf ("buffer [% 2D]: % 3d \ n", producepos, buffer_critical [producepos]); // enable the buffer written by the producer to be used by multiple consumers, implement read/write synchronization; releasesemaphore (h_semaphore [m_serial], n_thread, null);} // void consume (void * P) of the consumer process {// local variable Declaration; dwordwait_for_semaphore, m_delay; intm_serial, m_requestnum; // the serial number of the consumer thread and The number of requests; intm_thread_request [max_thread_num]; // The Request queue of the local consumer thread; // extract the information of the local thread to the local machine; m_serial = (threadinfo *) (p )) -> serial; m_delay = (DWORD) (threadinfo *) (p)-> delay * inte_per_sec); m_requestnum = (threadinfo *) (p )) -> n_request; For (INT I = 0; I <m_requestnum; I ++) m_thread_request [I] = (threadinfo *) (p)-> thread_request [I]; sleep (m_delay); // cyclically consume the required products for (INT I = 0; I <m_requestnum; I ++) {// request to consume the next product printf ("Consumer % 2D request to consume % 2D product \ n ", m_serial, m_thread_request [I]); // if the corresponding producer does not produce, wait; If the producer is produced, the number of consumers allowed is-1; implement read/write synchronization; wait_for_semaphore = waitforsingleobject (h_semaphore [m_thread_request [I],-1 ); // query the number of products in the buffer zone int bufferpos = findbufferposition (m_thread_request [I]); // start the consumption Processing of the specific buffer zone, the read and read operations are mutually exclusive in the buffer zone. // after entering the critical section, the system executes the Consumption Action. After completing the request, it notifies another consumer that the request has been met; at the same time, if the corresponding product is used up, the corresponding processing will be done; and the interface for corresponding actions will be provided // display; the corresponding processing means clearing the corresponding buffer zone, and add a semaphore representing the empty buffer; entercriticalsection (& pc_cri Tical [bufferpos]); printf ("Consumer % 2D starts to consume % 2D product \ n", m_serial, m_thread_request [I]); (threadinfo *) (p )) -> thread_request [I] =-1; if (! Ifinotherrequest (m_thread_request [I]) {buffer_critical [bufferpos] =-1; // flag the buffer is empty; printf ("Consumer % 2D successfully consumed % 2D: \ n ", m_serial, m_thread_request [I]); printf ("buffer [% 2D]: % 3d \ n", bufferpos, buffer_critical [bufferpos]); releasesemaphore (empty_semaphore, 1, null);} else {printf ("Consumer % 2D successfully consumed product % 2D \ n", m_serial, m_thread_request [I]);} // leave the critical section leavecriticalsection (& pc_critical [bufferpos]);}