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

  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. 07-SSH综合案例:前台用户模块:结构创建及注册页面跳转

    现在就不要直接访问一个JSP,要通过一个Action映射过去.我现在点击要去一个注册的页面 这还不是一个真正的注册,只是一个页面的跳转. 1.5.2 用户模块 注册功能: 在index.jsp页面中点 ...

  2. linux install jupyter notebook

    install sudo pip install jupyter notebook start sudo jupyter notebook 一般,文件目录默认在你启动的位置.你可以在notebook里 ...

  3. thinkphp 3.2.3 addAll方法的坑

    在批量插入一组数据的时候,总是提示以下错误 Insert value list does not match column list: Column count doesn't match value ...

  4. VMTurbo:应对散乱虚拟机的强劲工具

    随着服务器虚拟化技术越来越成熟,虚拟机散乱(VM sprawl)和主机资源管理成为了虚拟化数据中心的管理员眼里的两大问题.面对这种情形,一种可行的解决办法就是使用一款名为VMTurbo(vmturbo ...

  5. 6-查看centos中的用户和用户组

    转载自:http://www.cnblogs.com/ermao0423/p/9510636.html 查看centos中的用户和用户组 1.用户列表文件:/etc/passwd/ 2.用户组列表文件 ...

  6. advance shading--光源的类型

    我们这里讨论的光源类型都有一个相同点,就是,我们考量的都是光源上的一个点,对于物体表面上一个点的影响,也就是说立体角趋近为零的情况. 这里光源分为两类,一类是方向光,假设光源在无限远处.另一类是点光源 ...

  7. file_get_contents()

    file_get_contents()类似于curl接口调用

  8. Ubuntu在命令行下将默认语言改为英语

    将Ubuntu安装成中文版,需要将默认语言改为英文. 用vi(或nano等文本编辑器)打开 /etc/default/locale 文件 将原来的配置内容修改为 LANG=”en_US.UTF-8″ ...

  9. Java 设计模式系列(七)桥接模式

    Java 设计模式系列(七)桥接模式 桥接模式(Bridge)是一种结构型设计模式.Bridge 模式基于类的最小设计原则,通过使用封装.聚合及继承等行为让不同的类承担不同的职责.它的主要特点是把抽象 ...

  10. C#的链表操作[数据结构-线性表]

    链式存储结构图解: 上图中,a1,是数据,紧跟着后面的d1是下一个节点的地址值.也就是一个节点的最后存储的是下一个节点的地址值,最后一个节点的存储的下一个地址值是null,代表链表结束. 1,定义链表 ...