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

  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. oracle数据库在sys下直接修改用户密码

    首先用sys登录上去, 在命令窗口或者是能执行输入sql语句的地方输入下面代码, 回车就好 alter user you_username(要修改的用户名) identified by you_pas ...

  2. iOS App图标和启动画面尺寸

    注意:iOS所有图标的圆角效果由系统生成,给到的图标本身不能是圆角的. 1. 桌面图标 (app icon) for iPhone6 plus(@3x) : 180 x 180 for iPhone ...

  3. 2.QWidget类

    简述: QWidget类是所有用户界面对象的基类. Widget是用户界面的基本单元:它从窗口系统接收鼠标,键盘和其他事件,并在屏幕上绘制自己. 每个Widget都是矩形的,它们按照Z-order进行 ...

  4. PhpStorm 合理标注目录让索引和扫描更加地高效

    在项目开发过程中,以下几种情况让 PhpStorm 加重了索引扫描的负担: 1.npm install 之后产生的 node_modules 目录 2.runtime 运行时产生的目录 3.stora ...

  5. mysql资源总结

    MySQL查询语句大全集锦 http://www.jb51.net/article/85889.htm linux下mysql命令大全 http://www.cnblogs.com/mfryf/arc ...

  6. 441. Arranging Coins

    static int wing=[]() { std::ios::sync_with_stdio(false); cin.tie(NULL); ; }(); class Solution { publ ...

  7. 声音处理(Cool Edit)

    平直化处理 上升半音

  8. Scala程序编译运行

    1.编译 Scala演示代码如下: <pre name="code" class="plain">/** * @author Administrat ...

  9. C#基础入门 十一

    C#基础入门 十一 复选框 复选框的应用--问卷调查 实现描述:通过问卷调查统计性别和下班后回家的方式,单击"提交"按钮,通过消息框显示所提交的信息.运行结果如下图所示(图27): ...

  10. [Erlang33]使用recon从网页查看Erlang运行状态

    0.需求分析 Erlang最好的卖点之一就是提供了一个非常强大的shell来查看Node运行时的各种状态,可以进行各种各样的内部查看,在运行时调试和分析,热更新代码.   但是总有一些在生产环境下要慎 ...