///////////////////////////////////////////////////////////////////// // deadlock.cpp - demonstrate deadlock condition // // // // Two threads attempt to run to completion, but second one // // often blocks, waiting for output to finish, so only first // // finishes. // // // // Jim Fawcett, CSE691 - Software Modeling & Analysis, Fall 2000 // ///////////////////////////////////////////////////////////////////// #include #include #include using namespace std; CRITICAL_SECTION cs1; CRITICAL_SECTION cs2; int shared1 = 0, shared2 = 2; // // Deadlock can occur when two or more threads attempt to lock // two or more resources, e.g.: // thread A holds resource 1 and attempts to acquire resource 2 // thread B holds resource 2 and attempts to acquire resource 1 // This is simulated in the two thread processing functions below. // //----< thread processing function >--------------------------- unsigned int __stdcall threadProc1(void *pData) { int i; for(i=0; i<1000; i++) { EnterCriticalSection(&cs2); EnterCriticalSection(&cs1); int myShared2 = shared2; LeaveCriticalSection(&cs1); Sleep(10); shared1 += myShared2; cout << '.'; LeaveCriticalSection(&cs2); } *((int*)pData) = shared1; return 0; } //----< thread processing function >--------------------------- unsigned int __stdcall threadProc2(void *pData) { int i; for(i=0; i<1000; i++) { EnterCriticalSection(&cs1); int myShared2 = shared2; EnterCriticalSection(&cs2); shared1 += myShared2; cout << '.'; Sleep(10); LeaveCriticalSection(&cs2); LeaveCriticalSection(&cs1); } *((int*)pData) = shared1; return 0; } // //----< entry point for process >------------------------------ void main() { cout << "\n Demonstrate the Operation of Mult-threaded Code " << "\n With Deadlock Condition" << "\n=======================================================\n\n"; // define an array of handles to threads, needed to wait // for their completion InitializeCriticalSection(&cs1); InitializeCriticalSection(&cs2); const int NumHandles = 2; HANDLE thHand[NumHandles]; int count1 = 0, count2 = 0; // 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 *Arg1 = &count1; // pointer to argument // start first thread thHand[0] = (HANDLE)_beginthreadex( Security, StackSize, threadProc1, Arg1, InitFlag, &ThreadID[0] ); // // define argument values for thread #2 _beginthreadex unsigned int(__stdcall threadProc2)(void*); void *Arg2 = &count2; // start second thread thHand[1] = (HANDLE)_beginthreadex( Security, StackSize, threadProc2, Arg2, InitFlag, &ThreadID[1] ); // tell process to wait for both threads to complete // before terminating BOOL fwait = TRUE; // wait for first unsignaled handle DWORD timeOut = INFINITE; // time out in milliseconds WaitForMultipleObjects(NumHandles, thHand, fwait, timeOut); CloseHandle(thHand[0]); // return resources CloseHandle(thHand[1]); // return resources DeleteCriticalSection(&cs1); DeleteCriticalSection(&cs2); Sleep(5); cout << "\n count1 = " << count1 << "\n count2 = " << count2 << "\n\n"; }