zoukankan      html  css  js  c++  java
  • C语言多线程编程二

    一. 线程通信----事件:

      1.一对一模式:

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    //互斥解决线程冲突
    //事件解决线程通信
    //临界区解决线程冲突
    //时间同步线程
    
    HANDLE event[5] = { 0 };
    HANDLE hd[5] = { 0 };
    
    DWORD WINAPI Zhang(void *p)
    {
        int i = 1;
        printf("张%d次说:I love you Li.
    ", i);
        Sleep(1000);
        SetEvent(event[1]);
    
        while (++i)
        {
            WaitForSingleObject(event[0], INFINITE);    //无限等待一个信号
            printf("张%d次说:I love you Li.
    ", i);
            Sleep(1000);
            //ResetEvent(event[0]);    //信号复位
            SetEvent(event[1]);
        }
    
        return 0;
    }
    DWORD WINAPI Li(void *p)
    {
        int i = 0;
        while (++i)
        {
            WaitForSingleObject(event[1], INFINITE);    //无限等待一个信号
            printf("李%d次说:I love you too.
    ", i);
            Sleep(1000);
            //ResetEvent(event[1]);    //信号复位
            SetEvent(event[0]);
        }
    
        return 0;
    }
    
    void main()
    {
        //第二个参数代表:自动FALSE、手动TRUE(需要reset)
        //第三个参数信号状态
        //第四个参数标记名称
        //event[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
        //event[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
    
        event[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
        event[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
    
        hd[0] = CreateThread(NULL, 0, Zhang, NULL, 0, NULL);
        hd[1] = CreateThread(NULL, 0, Li, NULL, 0, NULL);
    
        WaitForMultipleObjects(2, hd, TRUE, INFINITE);
    
        system("pause");
    }

       2. 一对一中介者模式:

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    //互斥解决线程冲突
    //事件解决线程通信
    //临界区解决线程冲突
    //时间同步线程
    
    HANDLE event[5] = { 0 };
    HANDLE hd[5] = { 0 };
    
    char str[256] = { 0 };    //全局变量,存放说的内容
    
    DWORD WINAPI Wang(void *p)
    {
        int i = 0;
        int k = 0;    //判断是哪个信号
    
        while (++i)
        {
            if (k == 0)
            {
                WaitForSingleObject(event[1], INFINITE);    //无限等待一个信号
                printf("媒婆读取%d次:%s
    ", i,str);
                Sleep(1000);
                SetEvent(event[2]);
    
                k = 1;
            }
            else
            {
                WaitForSingleObject(event[3], INFINITE);    //无限等待一个信号
                printf("媒婆读取%d次:%s
    ", i, str);
                Sleep(1000);
                SetEvent(event[0]);
    
                k = 0;
            }
    
        }
    
        return 0;
    }
    
    DWORD WINAPI Zhang(void *p)
    {
        int i = 1;
        /*printf("张%d次说:I love you Li.
    ", i);*/
        memset(str, '0', 256);
        sprintf(str,"张%d次说:I love you Li.
    ", i);
        Sleep(1000);
        SetEvent(event[1]);
    
        while (++i)
        {
            WaitForSingleObject(event[0], INFINITE);    //无限等待一个信号
            /*printf("张%d次说:I love you Li.
    ", i);*/
            memset(str, '0', 256);
            sprintf(str,"张%d次说:I love you Li.
    ", i);
            Sleep(1000);
            //ResetEvent(event[0]);    //信号复位
            SetEvent(event[1]);
        }
    
        return 0;
    }
    DWORD WINAPI Li(void *p)
    {
        int i = 0;
        while (++i)
        {
            WaitForSingleObject(event[2], INFINITE);    //无限等待一个信号
            /*printf("李%d次说:I love you too.
    ", i);*/
            memset(str, '0', 256);
            sprintf(str,"李%d次说:I love you too.
    ", i);
            Sleep(1000);
            //ResetEvent(event[1]);    //信号复位
            SetEvent(event[3]);
        }
    
        return 0;
    }
    
    void main()
    {
        //第二个参数代表:自动FALSE、手动TRUE(需要reset)
        //第三个参数信号状态
        //第四个参数标记名称
        //event[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
        //event[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
    
        event[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
        event[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
        event[2] = CreateEvent(NULL, FALSE, FALSE, NULL);
        event[3] = CreateEvent(NULL, FALSE, 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, Wang, NULL, 0, NULL);
    
        WaitForMultipleObjects(3, hd, TRUE, INFINITE);
    
        system("pause");
    }

      3. 一对多广播模式:

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    //互斥解决线程冲突
    //事件解决线程通信
    //临界区解决线程冲突
    //时间同步线程
    HANDLE event[5] = { 0 };
    HANDLE hd[10] = { 0 };
    
    char ch[10] = { 'A','B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
    char str[256] = { 0 };
    
    DWORD WINAPI ZhangGirlFriend(void *p)
    {
        char *pch = p;
        printf("I am %c ZhangGirlFrend.
    ", *pch);
    
        if (*pch == 'A')
        {
            MessageBoxA(0, "1", "1", 0);
            sprintf(str,"张女友-%c speak: xiaohaha 
    ", *pch);
            SetEvent(event[0]);
        }
    
        int i = 0;
        while (++i)
        {
            WaitForSingleObject(event[0], INFINITE);
            printf("ZhangGirlFriend-%c read %s
    ", *pch, str);
            Sleep(1000);
            ResetEvent(event[0]);
        }
    
        return 0;
    }
    
    void main()
    {
        //第二个参数代表:自动FALSE(收到一次自动清空一次)、手动TRUE(需要reset)
        //第三个参数信号状态
        //第四个参数标记名称
        event[0] = CreateEventA(NULL, TRUE, FALSE, "msg");    //一直等待消息
    
        for (int i = 0; i < 10; i++)
        {
            hd[i] = CreateThread(NULL, 0, ZhangGirlFriend, &ch[i], 0, NULL);
        }
    
        WaitForMultipleObjects(10, hd, TRUE, INFINITE);
    
        system("pause");
    }

    二. 信号量:

      1. 信号量用作“关卡”的作用:

    //信号量-->关卡的作用
    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    #define id "Zhang"
    #define MAX 3
    
    //0 无限等待
    DWORD WINAPI myworker(void *p)
    {
        int *pint = p;
        printf("myworker%d is running...
    ", *pint);
    
        HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, id);    //打开一个信号
        if (myhsem)
        {
            printf("myworker%d is waiting...
    ", *pint);
            //初始时信号为0,为0就会死锁,信号量不减
            //不为0的情况下,信号量-1
            if (WaitForSingleObject(myhsem, INFINITE) == WAIT_OBJECT_0)    //等到了信号
            {
                printf("myworker%d is getting.
    ", *pint);
                Sleep(3000);
    
                printf("myworker%d is leaving.
    ", *pint);
                ReleaseSemaphore(myhsem, 1, NULL);//释放资源 +1
                CloseHandle(myhsem);//执行完成退出
            }
        }
    
        return 1;
    }
    
    void main()
    {
        //创建信号对象
        HANDLE hSEM = CreateSemaphore(NULL, 0, MAX, id);//开辟一个信号,最大计数是3
    
    
        int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
    
        HANDLE hd[10] = { 0 };
        for (int i = 0; i < 10; i++)
        {
            hd[i] = CreateThread(NULL, 0, myworker, a + i, 0, NULL);    //创建10个线程
        }
        Sleep(5000);
    
    
        printf("激活线程.
    ");
        ReleaseSemaphore(hSEM, MAX, NULL);//最多一次放过3个 +3
    
        WaitForMultipleObjects(10, hd, TRUE, INFINITE);
    
        CloseHandle(hSEM);
    
        system("pause");
    }

      2. 信号量实现互斥:

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    int num = 0;
    
    //互斥量,只能让一个线程运行,其他休眠
    //信号量,可以让多个线程运行,其他线程休眠
    //临界区,只能让一个线程运行,其他休眠
    //原子操作,操作速度最快
    //事件也可以实现互斥
    DWORD WINAPI add(void *p)
    {
        HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, "Hello");    
        if (myhsem)
        {
    
            if (WaitForSingleObject(myhsem, INFINITE) == WAIT_OBJECT_0)    //等到了信号
            {
                for (int i = 0; i < 10000; i++)
                {
                    num++;
                }
    
                ReleaseSemaphore(myhsem, 1, NULL);//释放资源 +1
                CloseHandle(myhsem);//执行完成退出
            }
        }
        else
        {
            printf("信号量获取失败.
    ");
        }
    
        return 1;
    }
    
    void main()
    {
        HANDLE hSEM = CreateSemaphore(NULL, 0, 1, "Hello");
    
        HANDLE hd[64] = { 0 };
        for (int i = 0; i < 64; i++)
        {
            hd[i] = CreateThread(NULL, 0, add, NULL, 0, NULL);    //创建64个线程
        }
        Sleep(2000);
    
        printf("激活线程.
    ");
        ReleaseSemaphore(hSEM, 1, NULL);    //一次放过一个
    
        WaitForMultipleObjects(64, hd, TRUE, INFINITE);
    
        printf("%d
    ", num);
    
        CloseHandle(hSEM);
    
        system("pause");
    }

    三. 互斥锁:

      相关函数如下:

        第一个 InitializeSRWLock
        函数功能:初始化读写锁
        函数原型:VOID InitializeSRWLock(PSRWLOCK SRWLock);
        函数说明:初始化(没有删除或销毁SRWLOCK的函数,系统会自动清理)


        第二个 AcquireSRWLockExclusive
        函数功能:写入者线程申请写资源。
        函数原型:VOID AcquireSRWLockExclusive(PSRWLOCK SRWLock);

        第三个 ReleaseSRWLockExclusive
        函数功能:写入者线程写资源完毕,释放对资源的占用。
        函数原型:VOID ReleaseSRWLockExclusive(PSRWLOCK SRWLock);

        第四个 AcquireSRWLockShared
        函数功能:读取者线程申请读资源。
        函数原型:VOID AcquireSRWLockShared(PSRWLOCK SRWLock);

        第五个 ReleaseSRWLockShared
        函数功能:读取者线程结束读取资源,释放对资源的占用。
        函数原型:VOID ReleaseSRWLockShared(PSRWLOCK SRWLock);

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    int num = 6400000;
    SRWLOCK g_lock;    
    
    //注意一个线程仅能锁定资源一次,不能多次锁定资源。
    DWORD WINAPI read(void *p)
    {
        AcquireSRWLockShared(&g_lock);    //读取期间锁定数据,数据无法被修改
    
        int i = 0;
        while (1)
        {
            Sleep(1000);
            printf("第%d秒num=%d
    ", i, num);
    
            if (i == 10)
            {
                break;
            }
    
            i++;
        }
    
        ReleaseSRWLockShared(&g_lock);
    
        return 1;
    }
    
    
    //改变一个变量的时候需要锁定
    DWORD WINAPI write(void *p)
    {
        AcquireSRWLockExclusive(&g_lock);    //锁定写入
        printf("开始写入...
    ");
        for (int i = 0; i < 100000; i++)
        {
            num--;
            //Sleep(10);
        }
        ReleaseSRWLockExclusive(&g_lock);
        printf("结束写入...
    ");
        return 1;
    }
    
    void main()
    {
        InitializeSRWLock(&g_lock);    //初始化互斥锁
    
        CreateThread(NULL, 0, read, NULL, 0, NULL);
    
        HANDLE hd[64];
        for (int i = 0; i < 64; i++)
        {
            hd[i] = CreateThread(NULL, 0, write, NULL, 0, NULL);
        }
        WaitForMultipleObjects(64, hd, TRUE, INFINITE);
    
        printf("last=%d
    ", num);
    
        system("pause");
    }

     四. 跨进程通信:

    1. 信号量mutex 跨进程通信:

      文件mutex1.c :

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    char name[100] = "Zhang love Li";
    
    void main()
    {
        HANDLE mutex = OpenMutexA(MUTEX_ALL_ACCESS, TRUE, name);
        if (mutex == NULL)
        {
            printf("打开失败!
    ");
            system("pause");
            return;
        }
        printf("等待------
    ");
    
        DWORD res = WaitForSingleObject(mutex, 10000);
        switch (res)
        {
        case WAIT_OBJECT_0:
            printf("收到信号---
    ");
            break;
        case WAIT_TIMEOUT:
            printf("超时没有收到---
    ");
            break;
        case WAIT_ABANDONED:
            printf("另外一个进程意外终止---
    ");
            break;
        default:
            break;
        }
    
        CloseHandle(mutex);
        system("pause");
    }

      文件mutex2.c :

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    char name[100] = "Zhang love Li";
    
    void main()
    {
        HANDLE mutex = CreateMutexA(NULL, TRUE, name);
        printf("创建成功!
    ");
        char ch = getchar();
    
        ReleaseMutex(mutex);        //离开互斥区
        printf("触发互斥量.
    ");
        CloseHandle(mutex);
    
        system("pause");
    }

      运行结果:

     2. 事件 event 跨进程通信:

      文件event.c :

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    char name[100] = "Zhang love Li";
    
    //只有mutex可以感知丢失,event无法感知
    void main()
    {
        HANDLE event = CreateEventA(NULL, FALSE, FALSE, name);
        printf("创建成功!
    ");
        char ch = getchar();
    
        SetEvent(event);
        printf("触发event.
    ");
        CloseHandle(event);
    
        system("pause");
    }

      文件 wait.c :

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    char name[100] = "Zhang love Li";
    
    void main()
    {
        HANDLE event = OpenEventA(EVENT_ALL_ACCESS, TRUE, name);//打开事件
        if (event == NULL)
        {
            printf("打开失败!
    ");
            system("pause");
            return;
        }
        printf("等待------
    ");
    
        DWORD res = WaitForSingleObject(event, 10000);
        switch (res)
        {
        case WAIT_OBJECT_0:
            printf("收到信号---
    ");
            break;
        case WAIT_TIMEOUT:
            printf("超时没有收到---
    ");
            break;
        case WAIT_ABANDONED:
            printf("另外一个进程意外终止---
    ");
            break;
        default:
            break;
        }
    
        CloseHandle(event);
        system("pause");
    }

     3. 信号 semaphore 跨进程通信:

      semaphore.c :

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    char name[100] = "Zhang love Li";
    
    //只有mutex可以感知丢失,event无法感知
    void main()
    {
        HANDLE hsem = CreateSemaphoreA(NULL, 0, 1, name);
        printf("创建成功!
    ");
        char ch = getchar();
    
        ReleaseSemaphore(hsem, 1, NULL);
        printf("触发信号量semaphore.
    ");
        CloseHandle(hsem);
    
        system("pause");
    }

      wait.c :

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    char name[100] = "Zhang love Li";
    
    void main()
    {
        HANDLE hsem = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, TRUE, name);
        if (hsem == NULL)
        {
            printf("打开失败!
    ");
            system("pause");
            return;
        }
        printf("等待------
    ");
    
        DWORD res = WaitForSingleObject(hsem, 10000);
        switch (res)
        {
        case WAIT_OBJECT_0:
            printf("收到信号---
    ");
            break;
        case WAIT_TIMEOUT:
            printf("超时没有收到---
    ");
            break;
        case WAIT_ABANDONED:
            printf("另外一个进程意外终止---
    ");
            break;
        default:
            break;
        }
    
        CloseHandle(hsem);
        system("pause");
    }

     五. 回调函数与定时器:

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    //回调函数,函数指针可以来调用
    VOID CALLBACK timerun(void *parg, DWORD timearg, DWORD timehigh)
    {
        DWORD dwindex = *(DWORD *)parg;
        printf("第%d次
    ", dwindex);
    }
    
    void main()
    {
        HANDLE timer1 = CreateWaitableTimerA(NULL, TRUE, "hello");//创建时钟
        if (timer1 == NULL)
        {
            printf("创建失败!
    ");
        }
    
        LARGE_INTEGER mytime;
        mytime.QuadPart = -50000000;    //单位是0.1微秒
    
        DWORD dwparam = 1;    //设置定时器
    
        if (SetWaitableTimer(timer1, &mytime, 1000, timerun, &dwparam, FALSE))//1000 1秒循环一次
        {
            printf("等待5秒后开始干活!
    ");
            for (int i = 0; i < 15; i++, dwparam++)    //循环调用多少次
            {
                SleepEx(INFINITE, TRUE);
            }
        }
    
        CancelWaitableTimer(timer1);//取消定时器
        CloseHandle(timer1);
    
        system("pause");
    }

    六. 原子操作:

    #include <stdio.h>
    #include <stdlib.h>
    
    void main()
    {
        volatile int i = 10;    //数据被意外改变的时候,强制读内存
        int a = i;
        printf("i=%d
    ", a);
    
        //偷偷改变i
        __asm
        {
            mov dword ptr[ebp-4],20h    //16进制 20h=32
        }
    
        int b = i;
        printf("i=%d
    ", b);
    
        system("pause");
    }

      上面结果在Debug模式下结果为:

            

      在Release模式下结果为:

            

  • 相关阅读:
    redis发布订阅
    redis学习笔记(面试题)
    redis安全 (error) NOAUTH Authentication required
    HDU3001 Travelling —— 状压DP(三进制)
    POJ3616 Milking Time —— DP
    POJ3186 Treats for the Cows —— DP
    HDU1074 Doing Homework —— 状压DP
    POJ1661 Help Jimmy —— DP
    HDU1260 Tickets —— DP
    HDU1176 免费馅饼 —— DP
  • 原文地址:https://www.cnblogs.com/si-lei/p/9506292.html
Copyright © 2011-2022 走看看