C語言多線程編程一

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");
}
相關文章
相關標籤/搜索