博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言多线程编程二
阅读量:4314 次
发布时间:2019-06-06

本文共 13087 字,大约阅读时间需要 43 分钟。

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

  1.一对一模式:

#include 
#include
#include
//互斥解决线程冲突//事件解决线程通信//临界区解决线程冲突//时间同步线程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 
#include
#include
//互斥解决线程冲突//事件解决线程通信//临界区解决线程冲突//时间同步线程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 
#include
#include
//互斥解决线程冲突//事件解决线程通信//临界区解决线程冲突//时间同步线程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 
#include
#include
#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 
#include
#include
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 
#include
#include
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");}

 四. 跨进程通信:

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

  文件mutex1.c :

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

  文件mutex2.c :

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

  运行结果:

 2. 事件 event 跨进程通信:

  文件event.c :

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

  文件 wait.c :

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

 3. 信号 semaphore 跨进程通信:

  semaphore.c :

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

  wait.c :

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

 五. 回调函数与定时器:

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

六. 原子操作:

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

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

        

  在Release模式下结果为:

        

 

转载于:https://www.cnblogs.com/si-lei/p/9506292.html

你可能感兴趣的文章
linux 获取系统屏幕分辨率
查看>>
MySQL 数据库常用命令小结
查看>>
log4net使用记录
查看>>
The Django Book 2.0--中文版
查看>>
编译式安装MYSQL
查看>>
更快找到正确的机器学习算法
查看>>
pair work 附加题解法(张艺 杨伊)
查看>>
记录我发现的第一个关于 Google 的 Bug
查看>>
linq操作符:转换操作符
查看>>
ng-深度学习-课程笔记-2: 神经网络中的逻辑回归(Week2)
查看>>
正则表达式的搜索和替换
查看>>
个人项目:WC
查看>>
地鼠的困境SSL1333 最大匹配
查看>>
flume+elasticsearch+kibana遇到的坑
查看>>
Javascript 高阶函数等
查看>>
【MM系列】在SAP里查看数据的方法
查看>>
pcre
查看>>
Redis基础
查看>>
[转]扩展chrome开发者工具
查看>>
排队论的C实现
查看>>