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

  1.一对一模式:

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

  2. 一对一中介者模式:

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

  3. 一对多广播模式:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h> //互斥解决线程冲突
//事件解决线程通信
//临界区解决线程冲突
//时间同步线程
HANDLE event[] = { };
HANDLE hd[] = { }; char ch[] = { 'A','B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
char str[] = { }; DWORD WINAPI ZhangGirlFriend(void *p)
{
char *pch = p;
printf("I am %c ZhangGirlFrend.\n", *pch); if (*pch == 'A')
{
MessageBoxA(, "", "", );
sprintf(str,"张女友-%c speak: xiaohaha \n", *pch);
SetEvent(event[]);
} int i = ;
while (++i)
{
WaitForSingleObject(event[], INFINITE);
printf("ZhangGirlFriend-%c read %s\n", *pch, str);
Sleep();
ResetEvent(event[]);
} return ;
} void main()
{
//第二个参数代表:自动FALSE(收到一次自动清空一次)、手动TRUE(需要reset)
//第三个参数信号状态
//第四个参数标记名称
event[] = CreateEventA(NULL, TRUE, FALSE, "msg"); //一直等待消息 for (int i = ; i < ; i++)
{
hd[i] = CreateThread(NULL, , ZhangGirlFriend, &ch[i], , NULL);
} WaitForMultipleObjects(, 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(); printf("myworker%d is leaving.\n", *pint);
ReleaseSemaphore(myhsem, , NULL);//释放资源 +1
CloseHandle(myhsem);//执行完成退出
}
} return ;
} void main()
{
//创建信号对象
HANDLE hSEM = CreateSemaphore(NULL, , MAX, id);//开辟一个信号,最大计数是3 int a[] = { ,,,,,,,,, }; HANDLE hd[] = { };
for (int i = ; i < ; i++)
{
hd[i] = CreateThread(NULL, , myworker, a + i, , NULL); //创建10个线程
}
Sleep(); printf("激活线程.\n");
ReleaseSemaphore(hSEM, MAX, NULL);//最多一次放过3个 +3 WaitForMultipleObjects(, hd, TRUE, INFINITE); CloseHandle(hSEM); system("pause");
}

  2. 信号量实现互斥:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h> int num = ; //互斥量,只能让一个线程运行,其他休眠
//信号量,可以让多个线程运行,其他线程休眠
//临界区,只能让一个线程运行,其他休眠
//原子操作,操作速度最快
//事件也可以实现互斥
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 = ; i < ; i++)
{
num++;
} ReleaseSemaphore(myhsem, , NULL);//释放资源 +1
CloseHandle(myhsem);//执行完成退出
}
}
else
{
printf("信号量获取失败.\n");
} return ;
} void main()
{
HANDLE hSEM = CreateSemaphore(NULL, , , "Hello"); HANDLE hd[] = { };
for (int i = ; i < ; i++)
{
hd[i] = CreateThread(NULL, , add, NULL, , NULL); //创建64个线程
}
Sleep(); printf("激活线程.\n");
ReleaseSemaphore(hSEM, , NULL); //一次放过一个 WaitForMultipleObjects(, 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 = ;
SRWLOCK g_lock; //注意一个线程仅能锁定资源一次,不能多次锁定资源。
DWORD WINAPI read(void *p)
{
AcquireSRWLockShared(&g_lock); //读取期间锁定数据,数据无法被修改 int i = ;
while ()
{
Sleep();
printf("第%d秒num=%d\n", i, num); if (i == )
{
break;
} i++;
} ReleaseSRWLockShared(&g_lock); return ;
} //改变一个变量的时候需要锁定
DWORD WINAPI write(void *p)
{
AcquireSRWLockExclusive(&g_lock); //锁定写入
printf("开始写入...\n");
for (int i = ; i < ; i++)
{
num--;
//Sleep(10);
}
ReleaseSRWLockExclusive(&g_lock);
printf("结束写入...\n");
return ;
} void main()
{
InitializeSRWLock(&g_lock); //初始化互斥锁 CreateThread(NULL, , read, NULL, , NULL); HANDLE hd[];
for (int i = ; i < ; i++)
{
hd[i] = CreateThread(NULL, , write, NULL, , NULL);
}
WaitForMultipleObjects(, hd, TRUE, INFINITE); printf("last=%d\n", num); system("pause");
}

四. 跨进程通信:

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

  文件mutex1.c :

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

  wait.c :

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h> char name[] = "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, );
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 <stdio.h>
#include <stdlib.h>
#include <Windows.h> //回调函数,函数指针可以来调用
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 = -; //单位是0.1微秒 DWORD dwparam = ; //设置定时器 if (SetWaitableTimer(timer1, &mytime, , timerun, &dwparam, FALSE))//1000 1秒循环一次
{
printf("等待5秒后开始干活!\n");
for (int i = ; i < ; i++, dwparam++) //循环调用多少次
{
SleepEx(INFINITE, TRUE);
}
} CancelWaitableTimer(timer1);//取消定时器
CloseHandle(timer1); system("pause");
}

六. 原子操作:

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

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

        

  在Release模式下结果为:

        

C语言多线程编程二的更多相关文章

  1. linux下C语言多线程编程实例

    用一个实例.来学习linux下C语言多线程编程实例. 代码目的:通过创建两个线程来实现对一个数的递加.代码: //包含的头文件 #include <pthread.h> #include ...

  2. C语言多线程编程

    HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUT ...

  3. Linux C语言多线程编程实例解析

    Linux系统下的多线程遵循POSIX线程接口,称为 pthread.编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a.顺便说一下,Linux ...

  4. Linux系统编程@多线程编程(二)

    线程的操作 线程标识 线程的ID表示数据类型:pthread_t (内核中的实现是unsigned long/unsigned int/指向pthread结构的指针(不可移植)几种类型) 1.对两个线 ...

  5. java多线程编程(二)

    1. wait 和 sleep 区别? 1.wait可以指定时间也可以不指定,sleep必须指定时间. 2.在同步中时,对cpu的执行权和锁的处理不同.  wait:释放执行权,释放锁.  sleep ...

  6. java多线程编程(二创建线程)

    1.概念           因为java是完全面向对象的,所以在java中,我们说的线程,就是Thread类的一个实例对象.所以,一个线程就是一个对象,它有自己字段和方法. 2.创建线程 创建线程有 ...

  7. Android多线程编程<二>Handler异步消息处理机制之Message

      Message(消息):       一. Message的字段:    在Android中,Message作为线程之间(主要是子线程和UI主线程之间)数据交换的载体,通过Handler去传递.它 ...

  8. C++多线程编程二

    1. 死锁与解锁: #include <iostream> #include <thread> #include <mutex> using namespace s ...

  9. C语言多线程编程 死锁解析

    1.假设有两个线程 A线程负责输出奇数.B线程负责输出偶数. 2.当A线程进入锁定状态是,主线程突然异常将A线程停止,这时将导致B线程也无法继续执行,处于死锁状态.如下代码: #include < ...

随机推荐

  1. 在Spring使用junit注解进行单元测试

    在Spring中可以使用junit配合注解进行单元测试 一.常用注解 1.@RunWith(SpringJUnit4ClassRunner.class),让测试运行于spring测试环境2.@Cont ...

  2. Server.Transfer和Response.Redirect的区别

    (1)Server.Transfer方法: Server.Transfer("m2.aspx");//页面转向(服务器上执行). 服务器停止解析本页,保存此页转向前的数据后,再使页 ...

  3. WdatePicker.js的使用方法 帮助文档 使用说明(时间控件)

    WdatePicker.js的使用方法 帮助文档 使用说明(时间控件)   4. 日期范围限制 静态限制 注意:日期格式必须与 realDateFmt 和 realTimeFmt 一致 你可以给通过配 ...

  4. shell如何传递变量到另一个脚本文件中

    http://www.jbxue.com/article/shell/20707.html本文介绍了shell脚本传递变量到另一个脚本文件中的方法,在脚本中调用另一脚本,即创建了一个子进程,感兴趣的朋 ...

  5. day25 map,filter,reduce 内置函数,作业

    =====================作业一#用map来处理字符串列表啊,把列表中所有人都变成sb,比方alex_sbname=['alex','wupeiqi','yuanhao']###### ...

  6. python多线程编程5: 条件变量同步-乾颐堂

    互斥锁是最简单的线程同步机制,Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还 ...

  7. CMAKE 教程前两章节学习

    原文 https://cmake.org/cmake-tutorial/ 以下是一个循序渐进的教程,它覆盖了CMAKE帮助改进的通常的构建系统的话题.许多话题在<掌握CMAKE>(< ...

  8. C++ 数据封装和抽象

    C++ 数据抽象 数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节. 数据抽象是一种依赖于接口和实现分离的编程(设计)技术. 让我们举一个现实生活中的真实例子 ...

  9. 20155334 2016-2017-2 《Java程序设计》第六周学习总结

    20155334 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 第十章:输入/输出 InputStream与OutputStream java将输入/输出抽 ...

  10. Android 4.3实现类似iOS在音乐播放过程中如果有来电则音乐声音渐小铃声渐大的效果

    目前Android的实现是:有来电时,音乐声音直接停止,铃声直接直接使用设置的铃声音量进行铃声播放. Android 4.3实现类似iOS在音乐播放过程中如果有来电则音乐声音渐小铃声渐大的效果. 如果 ...