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.\n", i);
    Sleep(1000);
    SetEvent(event[1]);

    while (++i)
    {
        WaitForSingleObject(event[0], INFINITE);    //无限等待一个信号
        printf("张%d次说:I love you Li.\n", 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.\n", 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\n", i,str);
            Sleep(1000);
            SetEvent(event[2]);

            k = 1;
        }
        else
        {
            WaitForSingleObject(event[3], INFINITE);    //无限等待一个信号
            printf("媒婆读取%d次:%s\n", 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.\n", i);*/
    memset(str, '0', 256);
    sprintf(str,"张%d次说:I love you Li.\n", i);
    Sleep(1000);
    SetEvent(event[1]);

    while (++i)
    {
        WaitForSingleObject(event[0], INFINITE);    //无限等待一个信号
        /*printf("张%d次说:I love you Li.\n", i);*/
        memset(str, '0', 256);
        sprintf(str,"张%d次说:I love you Li.\n", 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.\n", i);*/
        memset(str, '0', 256);
        sprintf(str,"李%d次说:I love you too.\n", 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.\n", *pch);

    if (*pch == 'A')
    {
        MessageBoxA(0, "1", "1", 0);
        sprintf(str,"张女友-%c speak: xiaohaha \n", *pch);
        SetEvent(event[0]);
    }

    int i = 0;
    while (++i)
    {
        WaitForSingleObject(event[0], INFINITE);
        printf("ZhangGirlFriend-%c read %s\n", *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...\n", *pint);

    HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, id);    //打开一个信号
    if (myhsem)
    {
        printf("myworker%d is waiting...\n", *pint);
        //初始时信号为0,为0就会死锁,信号量不减
        //不为0的情况下,信号量-1
        if (WaitForSingleObject(myhsem, INFINITE) == WAIT_OBJECT_0)    //等到了信号
        {
            printf("myworker%d is getting.\n", *pint);
            Sleep(3000);

            printf("myworker%d is leaving.\n", *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("激活线程.\n");
    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("信号量获取失败.\n");
    }

    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("激活线程.\n");
    ReleaseSemaphore(hSEM, 1, NULL);    //一次放过一个

    WaitForMultipleObjects(64, hd, TRUE, INFINITE);

    printf("%d\n", 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\n", i, num);

        if (i == 10)
        {
            break;
        }

        i++;
    }

    ReleaseSRWLockShared(&g_lock);

    return 1;
}


//改变一个变量的时候需要锁定
DWORD WINAPI write(void *p)
{
    AcquireSRWLockExclusive(&g_lock);    //锁定写入
    printf("开始写入...\n");
    for (int i = 0; i < 100000; i++)
    {
        num--;
        //Sleep(10);
    }
    ReleaseSRWLockExclusive(&g_lock);
    printf("结束写入...\n");
    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\n", num);

    system("pause");
}

猜你喜欢

转载自www.cnblogs.com/si-lei/p/9506292.html