1.原子访问:同一时刻只允许同一线程访问资源(变量) 关键字:volatile(防止编译优化,对特殊地址进行稳定访问)
可直接操作内存
2.关键段:同一时刻只允许一个线程访问一个代码段
InitializeCriticalSectionAndSpinCount(变量名,0)
例:
// Global variable CRITICAL_SECTION CriticalSection; int main( void ) { ... // Initialize the critical section one time only. if (!InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x00000400) ) return; ... // Release resources used by the critical section object. DeleteCriticalSection(&CriticalSection); } DWORD WINAPI ThreadProc( LPVOID lpParameter ) { ... // Request ownership of the critical section. EnterCriticalSection(&CriticalSection); // Access the shared resource. // Release ownership of the critical section. LeaveCriticalSection(&CriticalSection); ... return 1; }
3.互斥量:Mutex本质上说就是一把锁,提供对资源的独占访问,所以Mutex主要的作用是用于互斥
CreateMutex(安全属性,NULL,NULL(互斥量名字))
例:
#include <windows.h> #include <stdio.h> #define THREADCOUNT 2 HANDLE ghMutex; DWORD WINAPI WriteToDatabase( LPVOID ); int main( void ) { HANDLE aThread[THREADCOUNT]; DWORD ThreadID; int i; // Create a mutex with no initial owner ghMutex = CreateMutex( NULL, // default security attributes FALSE, // initially not owned NULL); // unnamed mutex if (ghMutex == NULL) { printf("CreateMutex error: %d\n", GetLastError()); return 1; } // Create worker threads for( i=0; i < THREADCOUNT; i++ ) { aThread[i] = CreateThread( NULL, // default security attributes 0, // default stack size (LPTHREAD_START_ROUTINE) WriteToDatabase, NULL, // no thread function arguments 0, // default creation flags &ThreadID); // receive thread identifier if( aThread[i] == NULL ) { printf("CreateThread error: %d\n", GetLastError()); return 1; } } // Wait for all threads to terminate WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE); // Close thread and mutex handles for( i=0; i < THREADCOUNT; i++ ) CloseHandle(aThread[i]); CloseHandle(ghMutex); return 0; } DWORD WINAPI WriteToDatabase( LPVOID lpParam ) { // lpParam not used in this example UNREFERENCED_PARAMETER(lpParam); DWORD dwCount=0, dwWaitResult; // Request ownership of mutex. while( dwCount < 20 ) { dwWaitResult = WaitForSingleObject( ghMutex, // handle to mutex INFINITE); // no time-out interval switch (dwWaitResult) { // The thread got ownership of the mutex case WAIT_OBJECT_0: __try { // TODO: Write to the database printf("Thread %d writing to database...\n", GetCurrentThreadId()); dwCount++; } __finally { // Release ownership of the mutex object if (! ReleaseMutex(ghMutex)) { // Handle error. } } break; // The thread got ownership of an abandoned mutex // The database is in an indeterminate state case WAIT_ABANDONED: return FALSE; } } return TRUE; }
4.事件:事件是内核对象,事件分为手动置位事件和自动置位事件。
事件可以由SetEvent()设置为有信号,由ResetEvent()来设值为无信号。
CreateEvent(安全属性(NULL),TRUE,FALSE,NULL(事件名称))
例
#include <windows.h> #include <stdio.h> #define THREADCOUNT 4 HANDLE ghWriteEvent; HANDLE ghThreads[THREADCOUNT]; DWORD WINAPI ThreadProc(LPVOID); void CreateEventsAndThreads(void) { int i; DWORD dwThreadID; // Create a manual-reset event object. The write thread sets this // object to the nonsignaled state when it finishes writing to a // shared buffer. ghWriteEvent = CreateEvent( NULL, // default security attributes TRUE, // manual-reset event FALSE, // initial state is nonsignaled TEXT("WriteEvent") // object name ); if (ghWriteEvent == NULL) { printf("CreateEvent failed (%d)\n", GetLastError()); return; } // Create multiple threads to read from the buffer. for(i = 0; i < THREADCOUNT; i++) { // TODO: More complex scenarios may require use of a parameter // to the thread procedure, such as an event per thread to // be used for synchronization. ghThreads[i] = CreateThread( NULL, // default security 0, // default stack size ThreadProc, // name of the thread function NULL, // no thread parameters 0, // default startup flags &dwThreadID); if (ghThreads[i] == NULL) { printf("CreateThread failed (%d)\n", GetLastError()); return; } } } void WriteToBuffer(VOID) { // TODO: Write to the shared buffer. printf("Main thread writing to the shared buffer...\n"); // Set ghWriteEvent to signaled if (! SetEvent(ghWriteEvent) ) { printf("SetEvent failed (%d)\n", GetLastError()); return; } } void CloseEvents() { // Close all event handles (currently, only one global handle). CloseHandle(ghWriteEvent); } int main( void ) { DWORD dwWaitResult; // TODO: Create the shared buffer // Create events and THREADCOUNT threads to read from the buffer CreateEventsAndThreads(); // At this point, the reader threads have started and are most // likely waiting for the global event to be signaled. However, // it is safe to write to the buffer because the event is a // manual-reset event. WriteToBuffer(); printf("Main thread waiting for threads to exit...\n"); // The handle for each thread is signaled when the thread is // terminated. dwWaitResult = WaitForMultipleObjects( THREADCOUNT, // number of handles in array ghThreads, // array of thread handles TRUE, // wait until all are signaled INFINITE); switch (dwWaitResult) { // All thread objects were signaled case WAIT_OBJECT_0: printf("All threads ended, cleaning up for application exit...\n"); break; // An error occurred default: printf("WaitForMultipleObjects failed (%d)\n", GetLastError()); return 1; } // Close the events to clean up CloseEvents(); return 0; } DWORD WINAPI ThreadProc(LPVOID lpParam) { // lpParam not used in this example. UNREFERENCED_PARAMETER(lpParam); DWORD dwWaitResult; printf("Thread %d waiting for write event...\n", GetCurrentThreadId()); dwWaitResult = WaitForSingleObject( ghWriteEvent, // event handle INFINITE); // indefinite wait switch (dwWaitResult) { // Event object was signaled case WAIT_OBJECT_0: // // TODO: Read from the shared buffer // printf("Thread %d reading from buffer\n", GetCurrentThreadId()); break; // An error occurred default: printf("Wait error (%d)\n", GetLastError()); return 0; } // Now that we are done reading the buffer, we could use another // event to signal that this thread is no longer reading. This // example simply uses the thread handle for synchronization (the // handle is signaled when the thread terminates.) printf("Thread %d exiting\n", GetCurrentThreadId()); return 1; }
5.信号量:信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。
例
#include <windows.h> #include <stdio.h> #define MAX_SEM_COUNT 10 #define THREADCOUNT 12 HANDLE ghSemaphore; DWORD WINAPI ThreadProc( LPVOID ); int main( void ) { HANDLE aThread[THREADCOUNT]; DWORD ThreadID; int i; // Create a semaphore with initial and max counts of MAX_SEM_COUNT ghSemaphore = CreateSemaphore( NULL, // default security attributes MAX_SEM_COUNT, // initial count MAX_SEM_COUNT, // maximum count NULL); // unnamed semaphore if (ghSemaphore == NULL) { printf("CreateSemaphore error: %d\n", GetLastError()); return 1; } // Create worker threads for( i=0; i < THREADCOUNT; i++ ) { aThread[i] = CreateThread( NULL, // default security attributes 0, // default stack size (LPTHREAD_START_ROUTINE) ThreadProc, NULL, // no thread function arguments 0, // default creation flags &ThreadID); // receive thread identifier if( aThread[i] == NULL ) { printf("CreateThread error: %d\n", GetLastError()); return 1; } } // Wait for all threads to terminate WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE); // Close thread and semaphore handles for( i=0; i < THREADCOUNT; i++ ) CloseHandle(aThread[i]); CloseHandle(ghSemaphore); return 0; } DWORD WINAPI ThreadProc( LPVOID lpParam ) { // lpParam not used in this example UNREFERENCED_PARAMETER(lpParam); DWORD dwWaitResult; BOOL bContinue=TRUE; while(bContinue) { // Try to enter the semaphore gate. dwWaitResult = WaitForSingleObject( ghSemaphore, // handle to semaphore 0L); // zero-second time-out interval switch (dwWaitResult) { // The semaphore object was signaled. case WAIT_OBJECT_0: // TODO: Perform task printf("Thread %d: wait succeeded\n", GetCurrentThreadId()); bContinue=FALSE; // Simulate thread spending time on task Sleep(5); // Release the semaphore when task is finished if (!ReleaseSemaphore( ghSemaphore, // handle to semaphore 1, // increase count by one NULL) ) // not interested in previous count { printf("ReleaseSemaphore error: %d\n", GetLastError()); } break; // The semaphore was nonsignaled, so a time-out occurred. case WAIT_TIMEOUT: printf("Thread %d: wait timed out\n", GetCurrentThreadId()); break; } } return TRUE; }
注:互斥量,事件,信号量 都可以跨进程通信
事件和信号量可以一起做任务
这些例子都是在vs的帮助里找到的~~~~