1. Windows下同時打開多個對話框:數組
#include <Windows.h> #include <process.h> //建立線程 void runmsg(void *p) { MessageBoxA(0, "hello world", "hello china", 0); } void main() { _beginthread(runmsg, 0, NULL); //啓動線程,函數地址,把函數當作線程的入口點 _beginthread(runmsg, 0, NULL); _beginthread(runmsg, 0, NULL); _beginthread(runmsg, 0, NULL); system("pause"); }
2. 多線程實現同步和異步:安全
#include <Windows.h> #include <stdlib.h> //typedef unsigned long DWORD; //#define WINAPI __stdcall 標準的呼叫 //typedef void far *LPVOID; DWORD WINAPI MyMseg(LPVOID lp) { MessageBoxA(0, "hello", "china", 0); }
void main() { HANDLE hthread; DWORD threadid; //保存線程編號 //異步執行: //for (int i = 0; i < 5; i++) //{ // hthread = CreateThread( // NULL, //安全屬性 // NULL, //堆棧大小 // MyMseg, //線程的入口點 // NULL, //函數的參數 // 0, //馬上執行 // &threadid //保存線程的id // ); //} //多線程實現同步: for (int i = 0; i < 5; i++) { hthread = CreateThread( NULL, //安全屬性 NULL, //堆棧大小 MyMseg, //線程的入口點 NULL, //函數的參數 0, //馬上執行 &threadid //保存線程的id ); WaitForSingleObject(hthread, INFINITE); //等待 CloseHandle(hthread); //關閉線程 } system("pause"); }
#include <stdio.h> #include <stdlib.h> #include <process.h> #include <Windows.h> void run(void *p) { int *px = p; printf("線程編號%d\n", *px); } void main() { int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; for (int i = 0; i < 10; i++) { HANDLE hd = (HANDLE) _beginthread(run, 0, &a[i]); //MyThread線程編號 WaitForSingleObject(hd, INFINITE); //單線程 //WaitForMultipleObjects() //多線程 } system("pause"); }
3. 多線程檢索:多線程
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> //生成隨機數 #include <process.h> int isfind = 0; //找到設置爲1,其餘線程就再也不查找 struct findInfo { int *pstart; //線程檢索的首地址 int length; //檢索的數據長度 int findNum; //須要查找的數據 int id; //線程的編號 }; void findIt(void *p) { struct findInfo *ps = p; //保存地址 printf("\n線程%d開始查找\n", ps->id); //遍歷首地址,長度爲10個元素 for (int *pf = ps->pstart; pf < ps->pstart + ps->length; pf++) { if (isfind == 1) { printf("線程%d結束查找,其餘線程已經找到\n", ps->id); return; } if (*pf == ps->findNum) { printf("線程%d結束查找,找到數據%d地址%p\n", ps->id, *pf, pf); isfind = 1; return; } } printf("線程%d結束查找\n", ps->id); } void main() { int a[100] = { 0 }; time_t ts; unsigned int data = time(&ts); srand(data); //隨機數種子 for (int i = 0; i < 100; i++) { a[i] = rand() % 100; printf("%4d", a[i]); if ((i+1) % 10 == 0) //每10個打印一行 { printf("\n"); } } int num; printf("輸入要查詢的數:\n"); scanf("%d", &num); struct findInfo info[10]; //結構體數組,保存每一個線程要查找的信息 for (int i = 0; i < 10;i++) { info[i].pstart = a + 10 * i; info[i].length = 10; info[i].findNum = num; info[i].id = i; _beginthread(findIt, 0, &info[i]); //調用線程 } system("pause"); }
4. 多線程切割:異步
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <Windows.h> #include <time.h> //生成隨機數 #include <process.h> int isfind = 0; //找到設置爲1,其餘線程就再也不查找 struct findInfo { int *pstart; //線程檢索的首地址 int length; //檢索的數據長度 int findNum; //須要查找的數據 int id; //線程的編號 }; #define M 100 //數據 #define N 8 //線程數量 void findIt(void *p) { struct findInfo *ps = p; //保存地址 printf("\n線程%d開始查找\n", ps->id); //遍歷首地址,長度爲10個元素 for (int *pf = ps->pstart; pf < ps->pstart + ps->length; pf++) { if (isfind == 1) { printf("線程%d結束查找,其餘線程已經找到\n", ps->id); return; } if (*pf == ps->findNum) { printf("線程%d結束查找,找到數據%d地址%p\n", ps->id, *pf, pf); isfind = 1; return; } } printf("線程%d結束查找\n", ps->id); } void main() { int a[100] = { 0 }; time_t ts; unsigned int data = time(&ts); srand(data); //隨機數種子 for (int i = 0; i < 100; i++) { a[i] = rand() % 100; printf("%4d", a[i]); if ((i+1) % 10 == 0) //每10個打印一行 { printf("\n"); } } int num; printf("輸入要查詢的數:\n"); scanf("%d", &num); struct findInfo info[N]; //結構體數組,保存每一個線程要查找的信息 if (M%N == 0) //前面能整除的狀況 { for (int i = 0; i < N; i++) { info[i].pstart = a + M/N * i; info[i].length = M/N; info[i].findNum = num; info[i].id = i; HANDLE hd = _beginthread(findIt, 0, &info[i]); } } else //不能整除的狀況 { for (int i = 0; i < N-1; i++) { info[i].pstart = a + M / (N-1) * i; info[i].length = M / (N - 1); info[i].findNum = num; info[i].id = i; HANDLE hd = _beginthread(findIt, 0, &info[i]); } //info[N-1]; int i = N - 1; info[i].pstart = a + M / (N - 1) * i; info[i].length = M % (N - 1); info[i].findNum = num; info[i].id = i; HANDLE hd = _beginthread(findIt, 0, &info[i]); } system("pause"); }
5. 多線程衝突:函數
#include <stdio.h> #include <stdlib.h> #include <process.h> #include <Windows.h> #include <time.h> CRITICAL_SECTION cs; //臨界區,全局 int num = 0; //全局變量,多線程同時訪問會發生衝突 //10 * 100 * 100 DWORD WINAPI myfun(void *p) { for (int i = 0; i < 100; i++) { EnterCriticalSection(&cs); //進入臨界區 num++; LeaveCriticalSection(&cs); //離開臨界區 //Sleep(10); } return 0; } void main() { time_t start, end; time(&start); HANDLE hd[100]; for (int i = 0; i < 100; i++) { hd[i] = CreateThread(NULL, 0, myfun, NULL, 0, NULL); //hd[i] = _beginthread(myfun, 0, NULL); //線程數組,數組的每個元素都是一個線程 //WaitForSingleObject(hd[i], INFINITE); //等待單個的線程結束(同步) } WaitForMultipleObjects(100, hd, TRUE, INFINITE); //等待全部線程退出 time(&end); printf("%f\n", difftime(end, start)); printf("%d\n", num); DeleteCriticalSection(&cs); system("pause"); }
6. 多線程的操做:優化
#include <stdio.h> #include <stdlib.h> #include <process.h> #include <Windows.h> //_beginthread CreateThread 建立線程 //_endthread ExitThread 內部結束線程 TerminateThread 外部強制結束 //SuspendThread凍結 ResumeThread解凍 DWORD WINAPI fun(void *p) { int i = 0; while (++i) { printf("%d\n", i); if (i > 8000) { //_endthread(); //用於線程內部退出 ExitThread(0); //同上 } } return 0; } //主線程,主導做用,管理調度其餘線程 void main() { HANDLE hd = CreateThread(NULL, 0, fun, NULL, 0, NULL); system("pause"); SuspendThread(hd); //凍結線程 system("pause"); ResumeThread(hd); //解凍線程 system("pause"); TerminateThread(hd,0); //外部強行結束線程 system("pause"); }
7. 臨界區 Critical Section:spa
#include <stdio.h> #include <stdlib.h> #include <process.h> #include <Windows.h> #define N 10 //#define N 100 臨界區最大線程是64 int num = 0; CRITICAL_SECTION cs1; //定義臨界區,爲結構體變量 CRITICAL_SECTION cs2; DWORD WINAPI add(void *p) { EnterCriticalSection(&cs1); //進入臨界區,寫在for循環外,節省了在循環中反覆進入和退出臨界區 for (int i = 0; i < 10000; i++) { //EnterCriticalSection(&cs1); num++; //LeaveCriticalSection(&cs1); } LeaveCriticalSection(&cs1); //退出臨界區 return 0; } DWORD WINAPI sub(void *p) { EnterCriticalSection(&cs2); //進入臨界區,寫在for循環外,節省了在循環中反覆進入和退出臨界區 for (int i = 0; i < 10000; i++) { num--; } LeaveCriticalSection(&cs2); //退出臨界區 return 0; } void main() { InitializeCriticalSection(&cs1); //初始化臨界區結構體 InitializeCriticalSection(&cs2); { HANDLE hd[N]; for (int i = 0; i < N; i++) { hd[i] = CreateThread(NULL, 0, add, NULL, 0, NULL); //建立線程 //WaitForSingleObject(hd[i], INFINITE); } WaitForMultipleObjects(N, hd, TRUE, INFINITE); //等待所有線程退出 printf("num=%d\n", num); } { HANDLE hd[N]; for (int i = 0; i < N; i++) { hd[i] = CreateThread(NULL, 0, sub, NULL, 0, NULL); //建立線程 //WaitForSingleObject(hd[i], INFINITE); } WaitForMultipleObjects(N, hd, TRUE, INFINITE); //等待所有線程退出 printf("num=%d\n", num); } DeleteCriticalSection(&cs1); //釋放臨界區 DeleteCriticalSection(&cs2); system("pause"); }
8. 線程通訊-事件機制 event:線程
#include <stdio.h> #include <stdlib.h> #include <Windows.h> HANDLE event[3] = {0}; //事件 HANDLE hd[3] = { 0 }; //線程數組 DWORD WINAPI firstthread(void *p) { MessageBoxA(0, "1", "1", 0); printf("第1個線程執行完成.\n"); SetEvent(event[0]); //設置event信號 return 0; } DWORD WINAPI secondthread(void *p) { WaitForSingleObject(event[0], INFINITE); //等待event信號出現,才執行下一步 MessageBoxA(0, "2", "2", 0); printf("第2個線程執行完成.\n"); return 0; } void main() { event[0] = CreateEvent(NULL, TRUE, FALSE, NULL); //建立事件 event[1] = CreateEvent(NULL, TRUE, FALSE, NULL); hd[0] = CreateThread(NULL, 0, firstthread, NULL, 0, NULL); //建立線程 hd[1] = CreateThread(NULL, 0, secondthread, NULL, 0, NULL); WaitForMultipleObjects(2, hd, TRUE, INFINITE); printf("所有完成!\n"); system("pause"); }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <Windows.h> #include <memory.h> HANDLE event[4] = { 0 }; //事件 HANDLE hd[3] = { 0 }; //線程數組 char str[1024] = { 0 }; //表明聊天內容的緩衝區 CRITICAL_SECTION(cs); //臨界區 //0 張通知媒婆 //1 媒婆發給李 //2 李通知媒婆 //3 媒婆發給張 DWORD WINAPI Zhang(void *p) { int i = 1; EnterCriticalSection(&cs); //進入臨界區 memset(str, '\0', 1024); sprintf(str, "張第%d次說:I love you Li\n", i); LeaveCriticalSection(&cs); //離開臨界區 Sleep(1000); SetEvent(event[0]); while (++i) { WaitForSingleObject(event[3], INFINITE); EnterCriticalSection(&cs); //進入臨界區 memset(str, '\0', 1024); sprintf(str, "張第%d次說:I love you Li\n", i); LeaveCriticalSection(&cs); //離開臨界區 Sleep(1000); SetEvent(event[0]); } return 0; } DWORD WINAPI Li(void *p) { int i = 0; while (++i) { WaitForSingleObject(event[1], INFINITE); EnterCriticalSection(&cs); //進入臨界區 memset(str, '\0', 1024); sprintf(str,"李第%d次說:I love you too\n", i); LeaveCriticalSection(&cs); //離開臨界區 Sleep(1000); SetEvent(event[2]); } return 0; } DWORD WINAPI show(void *p) { int i = 0; while (++i) { WaitForSingleObject(event[0], INFINITE); EnterCriticalSection(&cs); //進入臨界區 printf("媒婆傳遞:%s\n", str); LeaveCriticalSection(&cs); //離開臨界區 Sleep(1000); SetEvent(event[1]); WaitForSingleObject(event[2], INFINITE); EnterCriticalSection(&cs); printf("媒婆傳遞:%s\n", str); LeaveCriticalSection(&cs); Sleep(1000); SetEvent(event[3]); } return 0; } void main() { InitializeCriticalSection(&cs); event[0] = CreateEvent(NULL, TRUE, FALSE, NULL); //建立事件 event[1] = CreateEvent(NULL, TRUE, FALSE, NULL); event[2] = CreateEvent(NULL, TRUE, FALSE, NULL); event[3] = CreateEvent(NULL, TRUE, FALSE, NULL); hd[0] = CreateThread(NULL, 0, Zhang, NULL, 0, NULL); //建立線程 hd[1] = CreateThread(NULL, 0, Li, NULL, 0, NULL); hd[2] = CreateThread(NULL, 0, show, NULL, 0, NULL); WaitForMultipleObjects(2, hd, TRUE, INFINITE); printf("所有完成!\n"); DeleteCriticalSection(&cs); system("pause"); }
9. 線程互斥量 mutex:指針
#include <stdio.h> #include <stdlib.h> #include <Windows.h> int num = 0; HANDLE mutex = NULL; //指針 DWORD WINAPI add(void *p) { WaitForSingleObject(mutex, INFINITE); for (int i = 0; i < 100000; i++) { num++; } ReleaseMutex(mutex); return 0; } void main() { mutex = CreateMutex(NULL, FALSE, NULL); //建立互斥量 if (mutex == NULL) { //建立失敗 } HANDLE hd[10]; //線程互斥,同一個互斥量只能解決64個線程 for (int i = 0; i < 10; i++) //建立10個線程 { hd[i] = CreateThread(NULL, 0, add, NULL, 0, NULL); if (mutex == NULL) { //建立失敗 } } WaitForMultipleObjects(10, hd, TRUE, INFINITE); printf("%d\n", num); for (int i = 0; i < 10; i++) //關閉每個線程資源 { CloseHandle(hd[i]); } CloseHandle(mutex); //關閉互斥量 system("pause"); }
10. 原子變量 valatile :code
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <Windows.h> void main0401() { //release 優化 //volatile 原子操做 強制讀內存 不考慮副本 for (volatile int i = 0; i < INT_MAX; i++) { } printf("over"); system("pause"); } volatile int num = 20; //現代編譯器作了優化,加不加volatile是同樣的 DWORD WINAPI msg(void *p) //讀 { int *px = (int *)p; while (1) { int data = *px; //強制讀內存 printf("%d\n", data); Sleep(1000); } } DWORD WINAPI cmsg(void *p) //寫 { int *px = (int *)p; while (1) { *px += 1; Sleep(10000); } } void main() { CreateThread(NULL, 0, msg, &num, 0, NULL); CreateThread(NULL, 0, cmsg, &num, 0, NULL); printf("over"); system("pause"); }
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <Windows.h> int num = 0; //多個線程同時訪問一個變量會發生衝突,同時寫入 //線程安全:一個變量是線程安全,多線程同時讀寫沒有偏差 //臨界區(Critical Section)、事件機制(event)、互斥量(Mutex) //原子操做的速度要快於 臨界區(Critical Section)、事件機制(event)、互斥量(Mutex) DWORD WINAPI runX(void *p) { for (int i = 0; i < 10000; i++) { //num++; InterlockedIncrement(&num); //num++保證是完整操做,我操做完成了後續才能繼續執行 } return 0; } void main() { HANDLE hd[50]; for (int i = 0; i < 50; i++) { hd[i] = CreateThread(NULL, 0, runX, NULL, 0, NULL); } WaitForMultipleObjects(50, hd, TRUE, INFINITE); printf("%d\n", num); system("pause"); }
11. 定時器 timer :
#include <stdio.h> #include <stdlib.h> #include <Windows.h> //單獨定時器只能用於同步通訊 void main0601() { HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL); //建立定時器 if (timer == NULL) { return; } LARGE_INTEGER time; // time.QuadPart = -20000000; //2秒 //單位是10^-7秒 0.1微秒 SetWaitableTimer(timer, &time, 0, NULL, 0, NULL); //設置定時器等待2秒 if (WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0) { printf("等待成功!\n"); } else { printf("等待失敗!\n"); } system("pause"); } HANDLE timer; DWORD WINAPI go1(void *p) { MessageBoxA(0, "1", "1", 0); timer = CreateWaitableTimer(NULL, TRUE, NULL); //建立定時器 LARGE_INTEGER time; // time.QuadPart = -50000000; //2秒 //單位是10^-7秒 0.1微秒 SetWaitableTimer(timer, &time, 0, NULL, 0, NULL); //設置定時器等待2秒 } DWORD WINAPI go2(void *p) { WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0; MessageBoxA(0, "2", "2", 0); printf("等待成功!\n"); } void main() { HANDLE hd = CreateThread(NULL, 0, go1, NULL, 0, NULL); WaitForSingleObject(hd, INFINITE); if (WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0) { CreateThread(NULL, 0, go2, NULL, 0, NULL); printf("等待成功!\n"); } else { printf("等待失敗!\n"); } system("pause"); }