///////////////////////////////////////////////////////////////////// // shareNoConflict.cpp - demonstrate sharing problem solution // // // // Two threads attempt to modify a shared string with // // serializing access. // // // // Jim Fawcett, CSE691 - Software Modeling & Analysis, Fall 2000 // ///////////////////////////////////////////////////////////////////// #include #include #include #include #include using namespace std; CRITICAL_SECTION cs; // // Here, we have eliminated problems with thread conflicts // sharing the common string pointed to by pData, as seen // in share1.cpp. // // We've done this by placing critical sections around each // modification of the string by either one of the threads. // Unless we do something to prevent it, the first thread will // capture the shared string and lock out the second because // almost all thread processing has to be locked. We can prevent // this unfair monopoly by making each thread relinquish the rest // of its time slice at the end of the loop, with Sleep(0), // giving other thread a chance to enter the critical section. // //----< thread processing function >--------------------------- unsigned int __stdcall threadProc1(void *pData) { Sleep(0); EnterCriticalSection(&cs); string *pStr = (string*)pData; if(pStr->size() == 0) (*pStr) = "\nThis is a string created by thread1"; int i; LeaveCriticalSection(&cs); for(i=0; i<55; i++) { EnterCriticalSection(&cs); if(pStr->size() < 70) pStr->append(", added by thread1"); else { cout << (*pStr).c_str(); *pStr = "\nstring created by thread1"; } LeaveCriticalSection(&cs); Sleep(0); // give other thread a chance } return 0; } // //----< thread processing function >--------------------------- unsigned int __stdcall threadProc2(void *pData) { EnterCriticalSection(&cs); string *pStr = (string*)pData; if(pStr->size() == 0) (*pStr) = "\nThis is a string created by thread2"; LeaveCriticalSection(&cs); int i; for(i=0; i<55; i++) { EnterCriticalSection(&cs); if(pStr->size() < 70) pStr->append(", added by thread2"); else { cout << (*pStr).c_str(); *pStr = "\nstring created by thread2"; } LeaveCriticalSection(&cs); Sleep(0); // give other thread a chance } return 0; } // //----< entry point for process >------------------------------ void main() { cout << "\n Demonstrate the Operation of Mult-threaded Code " << "\n using synchronized access to shared resources" << "\n=================================================\n\n"; InitializeCriticalSection(&cs); // define an array of handles to threads, needed to wait // for their completion const int NumHandles = 2; HANDLE thHand[NumHandles]; // define argument values for thread #1 _beginthreadex string shared; void* Security = NULL; // no security attributes unsigned int StackSize = 0; // stack size picked by OS unsigned int(__stdcall threadProc1)(void*); // name of thread function unsigned int InitFlag = 0; // start running unsigned int ThreadID[2]; // receives thread id void *Arg = &shared; // pointer to argument // start first thread thHand[0] = (HANDLE)_beginthreadex( Security, StackSize, threadProc1, Arg, InitFlag, &ThreadID[0] ); // start second thread thHand[1] = (HANDLE)_beginthreadex( Security, StackSize, threadProc2, Arg, InitFlag, &ThreadID[1] ); // tell process to wait for both threads to complete // before terminating BOOL fwait = TRUE; // wait for all handles DWORD timeOut = INFINITE; // time out in milliseconds WaitForMultipleObjects(NumHandles, thHand, fwait, timeOut); CloseHandle(thHand[0]); // return resources CloseHandle(thHand[1]); // return resources cout << "\n\n"; DeleteCriticalSection(&cs); }