20160227.CCPP体系详解(0037天)

Posted 尹成

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20160227.CCPP体系详解(0037天)相关的知识,希望对你有一定的参考价值。

程序片段(01):01.一对一模式.c+02.中介者模式.c+03.广播模式.c
内容概要:事件

///01.一对一模式.c
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

//01.关于多线程:
//  (临界区+互斥量):线程冲突
//  (事件):线程通信
//  (时间):同步线程
HANDLE eventArrA[2] =  0 ;
HANDLE threadArrA[2] =  0 ;

DWORD WINAPI haiHua(void * p)

    printf("海华第01次说:i love you fangFang, please help me debug! \\n");//信息通信内容
    Sleep(1000);//信息传递时间
    SetEvent(eventArrA[0]);//提示信息传到
    int i = 1;
    while (++i)
    
        WaitForSingleObject(eventArrA[1], INFINITE);//等待信息传到
        printf("海华第%02d次说:i love you fangFang, please help me debug! \\n", i);
        Sleep(1000);
        //ResetEvent(eventArrA[1]);//重置信息提示(手动)
        SetEvent(eventArrA[0]);
    

    return 0;


DWORD WINAPI fangFang(void * p)

    int i = 0;
    while (++i)
    
        WaitForSingleObject(eventArrA[0], INFINITE);
        printf("王芳第%02d次说:sorry! but i love you! \\n", i);
        Sleep(1000);
        SetEvent(eventArrA[1]);
    
    return 0;


//02.关于CreateEvent(arg1, arg2, arg3, arg4);
//  arg1:安全属性集---->通常用NULL
//  arg2:手动重置事件-->手动:TRUE|自动:FALSE
//      注:使用一次事件通知,用TRUE,使用多次事件通知,用FALSE
//      注:使用一次线程通信,通常用的是信号量机制,而不是事件机制
//  arg3:事件激活状态-->通常用FALSE
//  arg4:事件唯一名称-->自定义(便于检索指定事件)
int main01(void)

    eventArrA[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
    eventArrA[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
    threadArrA[0] = CreateThread(NULL, 0, haiHua, NULL, 0, NULL);
    threadArrA[1] = CreateThread(NULL, 0, fangFang, NULL, 0, NULL);
    WaitForMultipleObjects(2, threadArrA, TRUE, INFINITE);//维持多线程异步并发执行的状态

    system("");




//01.事件深入:
//  1.事件用于线程通信
//  2.事件的额外细节:三个案例
//      双方通话---->三方通话---->一对多模式
//      (相亲)            (媒婆)中介者     (广播)广播模式
//02.了解一些问题:
//  (临界区+互斥+原子变量):线程冲突
//  事件:线程通信
//  时间:同步线程
//03.什么是死锁?
//  编写事件的时候最容易遇到死锁的事情!
//04.现在我们需要几个信号量,而且这个信号量我们用什么来进行描述?
//  时间通知+信号量
//05.顺序不严密:
//  1.等待信号之后,信号需要复原才行,否则会出现不正常的情况(信号错乱!)
//  2.信号不同步和乱序的解决方案-收到信号之后进行复位
//      (1).信号复位情况--必须复位,某些情况之下自动复位,建议主动复位
//      (2).围绕信号:的False&TRUE的分别
//          第二个参数:密切相关-自动&手动[复位情况]
///02.中介者模式.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

HANDLE threadArrB[3] =  0 ;
HANDLE eventArrB[4] =  0 ;

char strB[256] =  0 ;//线程通信内容

//01.三方通话:中介者设计模式
//  海华向中介者:发出事件通知0
//      中介者等海华:等待事件通知0
//  中介者向芳芳:发出事件通知1
//      芳芳等中介者:等待事件通知1
//  芳芳向中介者:发出事件通知2
//      中介者等芳芳:等待事件通知2
//  中介者向海华:发出事件通知3
//      海华等中介者:等待事件通知3
//  海华向中介者:发出事件通知0
DWORD WINAPI haiHuaB(void * p)

    sprintf(strB, "海华第01次说:i love you fangFang, please help me debug! \\n");//发出通信内容
    Sleep(1000);//模拟通信时间
    SetEvent(eventArrB[0]);//提示通信到达
    int i = 1;
    while (++i)
    
        WaitForSingleObject(eventArrB[3], INFINITE);
        memset(strB, '\\0', 256);
        sprintf(strB, "海华第%02d次说:i love you fangFang, please help me debug! \\n", i);
        Sleep(1000);
        SetEvent(eventArrB[0]);
    
    return 0;


DWORD WINAPI ruiFuB(void * p)

    int i = 0;
    int status = 0;//切换通信对象
    while (++i)
    
        if (!status)
        
            WaitForSingleObject(eventArrB[0], INFINITE);
            printf("媒婆传递海华通信内容(传递次数:%02d): \\n", i);
            printf("\\t%s \\n", strB);
            Sleep(1000);
            SetEvent(eventArrB[1]);
            status = 1;
        
        else
        
            WaitForSingleObject(eventArrB[2], INFINITE);
            printf("媒婆传递芳芳通信内容(传递次数:%02d): \\n", i);
            printf("\\t%s \\n", strB);
            Sleep(1000);
            SetEvent(eventArrB[3]);
            status = 0;
        
    
    return 0;


DWORD WINAPI fangFangB(void * p)

    int i = 0;
    while (++i)
    
        WaitForSingleObject(eventArrB[1], INFINITE);
        memset(strB, '\\0', 256);
        sprintf(strB, "王芳第%02d次说:sorry! but i love you! \\n", i);
        Sleep(1000);
        SetEvent(eventArrB[2]);
    
    return 0;


int main02(void)

    eventArrB[0] = CreateEvent(NULL, FALSE, FALSE, L"haiHua");
    eventArrB[1] = CreateEvent(NULL, FALSE, FALSE, L"ruiFuToFang");
    eventArrB[2] = CreateEvent(NULL, FALSE, FALSE, L"fangFang");
    eventArrB[3] = CreateEvent(NULL, FALSE, FALSE, L"ruiFuToHua");
    threadArrB[0] = CreateThread(NULL, 0, haiHuaB, NULL, 0, NULL);
    threadArrB[1] = CreateThread(NULL, 0, ruiFuB, NULL, 0, NULL);
    threadArrB[2] = CreateThread(NULL, 0, fangFangB, NULL, 0, NULL);
    WaitForMultipleObjects(3, threadArrB, TRUE, INFINITE);

    system("pause");




//01.中介者模式&广播模式&图论模式[多对多]
//  中介者:三方
//  广播:一对多
//  图论:多对多
//注:多线程这块儿必须要会树和图
//02.一对多的情况下:
//  既可以采用数组进行管理也可以采用链表进行管理
//03.涉及到树的情况之下:
//  QQ群聊天儿多线程,练就数据结构
//04.一对多&多对多:
//  群聊原理:中介者-->每个人进行转发
//  中介者进行转发原理-->数组管理-->数组广播-->群聊模式
//05.流程梳理:
//  1.我发送一条消息,中介者收到之后,他进行群发动作
//  2.中介者的衍生模式-->形成闭环-->选好起始点
//06.编程思想:精髓
//  原则上一个消息全局变量读取特点
// 相当于是一个公告栏,权限读取
//07.操作:
//      定义全局变量,便于读取全局变量的数据
///03.广播模式.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

HANDLE threadArrC[10] =  0 ;
HANDLE eventArrC[1] =  0 ;

char strC[256] =  0 ;//线程通信内容
char chrArr[10] =  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K' ;//代表十个人

//01.一个线程发出事件通知消息,多条线程监听该事件通知消息
//  一对多的模式
DWORD WINAPI haiHuaC(void * p)

    char * pChr = (char *)p;
    printf("i am %c haiHua's gir friend! \\n", *pChr);
    if ('A' == *pChr)
    
        MessageBox(0, TEXT("1"), TEXT("1"), 0);//暂停通知线程
        sprintf(strC, "海华女友%c speak:xiaohuahua lovely! \\n", *pChr);//消息通知内容
        SetEvent(eventArrC[0]);//发出事件通知
        MessageBox(0, TEXT("1"), TEXT("1"), 0);//暂停通知线程
        sprintf(strC, "海华女友%c speak:xiaohuahua lovely! \\n", *pChr);//消息通知内容
        SetEvent(eventArrC[0]);//发出事件通知
    
    int i = 0;
    while (++i)
    
        WaitForSingleObject(eventArrC[0], INFINITE);//等待事件通知
        printf("haiHua's girl friend %c read %s! \\n", pChr, strC);
        Sleep(1000);
        ResetEvent(eventArrC[0]);
    

    return 0;


int main03(void)

    eventArrC[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
    for (int i = 0; i < 10; ++i)
    
        threadArrC[i] = CreateThread(NULL, 0, haiHuaC, &chrArr[i], 0, NULL);
    
    WaitForMultipleObjects(10, threadArrC, TRUE, INFINITE);

    system("pause");




//01.中介者设计模式之广播模式:QQ群聊原理
//  群聊-->数组-->链表-->环状-->局域网:环状结构[网络可靠性]
//02.QQ的开发:不仅有发送和收取消息-->所以线程非常多
//  信号对称-->需要进行手动进行事件的设置
//      一对一:自动
//      中介者:自动
//      一对多:手动
//      多对多:手动

程序片段(02):01.Semaphore.c+02.SemaphoreNew.c
内容概要:信号量

///01.Semaphore.c
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

//01.信号量:
//  1.类似于空位的特点:
//  2.空置多少个位置就可以容纳多少个并行线程执行
//注:当空余的位置为0的时候,也就不能在另起线程执行任务了
#define id L"haiHua"//信号ID
#define MAX 3//空位数

//02.多线程信号量(semaphore)通信:
//  1.特点:打开一个信号量(等同于检索一个指定ID名称的信号量)
//  2.格式:HANDLE mySema = OpenSemaphore(arg1, arg2, arg3);
//      arg1:信号量检索范围(SEMAPHORE_ALL_ACCESS)
//      arg2:继承特性
//      arg3:信号量检索名称(自定义名称,在固定范围内唯一标识信号量)
//  3.刚打开信号量的时候:
//      信号量的空位为0,也就是无法开启新的异步线程执行任务
//      信号量的空位为N,也就是说此刻可以开启N条异步线程执行任务代码
//注:空位为N,表示除开当前线程之外可以另起的异步线程个数
DWORD WINAPI myWorker(void * p)

    int * pInt = (int *)p;
    printf("worker:%d si running! \\n", *pInt);
    HANDLE mySema = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, id);//指定范围检索指定名称的信号量
    if (mySema)//判断信号量是否存在
    
        printf("worker:%d is waiting! \\n", *pInt);//表示当前线程处于判定信号量状态
        Sleep(1000);
        if (WaitForSingleObject(mySema, INFINITE) == WAIT_OBJECT_0)//等待空位为0
        //如果信号空位为0,也就是无法开启异步线程的情况
            printf("worker:%d is getting! \\n", *pInt);//此时只有当前线程获得CPU执行权,其它线程无法获取CPU可执行权
            Sleep(3000);
            printf("worker:%d is leaving! \\n", *pInt);
            ReleaseSemaphore(mySema, 1, NULL);//释放信号:只是打开一个空位,也就是可以开启另外一条异步线程进行执行了
            CloseHandle(mySema);//释放资源信号量资源
        
    
    return 1;


//03.创建信号量:
//  1.特点:初始化信号量对象
//  2.格式:HANDLE mySema = CreateSemaphore(arg1, arg2, arg3, arg4);
//      arg1:安全属性集
//      arg2:初始空位数
//      arg3:最大空位数
//      arg4:信号量名称
int main01(void)

    HANDLE mySema = CreateSemaphore(NULL, 0, MAX, id);
    HANDLE threadArr[10] =  0 ;
    for (int i = 0; i < 10; ++i)
    //由于当前信号量为0,因此多条执行同一段儿代码的时候,需要判定能否通过
        threadArr[i] = CreateThread(NULL, 0, myWorker, threadArr + i, 0, NULL);
    
    Sleep(5000);
    printf("激活状态! \\n");
    ReleaseSemaphore(mySema, MAX, NULL);//释放信号量
    WaitForMultipleObjects(10, threadArr, TRUE, INFINITE);
    CloseHandle(mySema);

    system("pause");




//01.信号量:Semaphore
//  1.量值:0-1-2-3
//  2.使用一次进行一次减数,到了一定的数据之后,做一些指定操作
//      当数据减到至0的时候,信号为0,在使用信号量的地方,处于停滞状态
//  3.信号量还可以做一些其他的限定操作
//  4.线程通信:用途
//  5.具备等待机制
//02.信号计数原理:
//  1.两个按键入口,多个行李
//  2.信号衰减原理:空位原理
//      信号为0的时候,没有空位为0,通过判断信号的空位情况,决定是否让线程干活儿
//      等待唤醒机制0与非0的区别(非0,线程可执行,0线程不可执行)
//03.关卡原理:
//  1.同时最多支持10000个人购票
//  2.如果超过10000个人,就需要排队
//  3.当10000个人购票完毕的时候,重新开启线程执行任务
//04.原理:if 0 等下去
//  1.同一个信号量
//  2.10个线程
//  3.状态判定:
//      0-->10个等待
//      5-->5个等待,5个执行
//          执行一次,减去一次-->信号量衰减
//  4.所有的线程都能够读取到该信号量
//      多个线程占用资源:等待执行状态
//      用完与没有用完(线程不可执行状态与线程可执行状态)
//05.信号量完全解析:
//  步骤一:
//      HANDLE hSEM=CreateSemaphore(NULL,0,MAX,id);
//      创建一个信号量,信号量的最大值为MAX,如果等于0的情况之下,它就在这儿死等下去
//  步骤二:
//      ReleaseSemaphore(mySema,MAX,NULL);//释放信号量,补充空位数量
//      一旦将信号量设定为5就会开始进行执行
//06.什么样儿的情况之下我们使用信号量?
//      实现两个线程的死锁状态,设定为1这个信号量,进或者不进
///02.SemaphoreNew.c
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

int num = 0;

//01.信号量的应用:
//  1.排队执行机制
//      让多个线程处于执行状态,让多个线程处于休眠状态
//  2.实现线程互斥
//      让一个线程处于执行状态,让其它所有线程处于等待状态
DWORD WINAPI add(void * p)

    HANDLE mySema = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, L"xiaobin");//打开信号量:
    if (mySema)
    
        if (WAIT_OBJECT_0 == WaitForSingleObject(mySema, INFINITE))
        //判断信号强弱(判断信号量的数目,也就是判断空位数目)
            for (int i = 0; i < 10000; ++i)
            
                ++num;
            
            ReleaseSemaphore(mySema, 1, NULL);
            CloseHandle(mySema);
        
    
    else
    
        printf("打开信号量失败! \\n");
    


int main02(void)

    //01.实现线程互斥的关键代码:
    //  最多只能有一个空位(最多只能同时有一条线程处于执行状态)
    HANDLE mySema = CreateSemaphore(NULL, 0, 1, L"xiaobin");
    HANDLE threadArr[64] =  0 ;
    for (int i = 0; i < 64; ++i)
    
        threadArr[i] = CreateThread(NULL, 0, add, NULL, 0, NULL);
    
    printf("激活线程");
    ReleaseSemaphore(mySema, 1, NULL);
    WaitForMultipleObjects(64, threadArr, TRUE, INFINITE);
    printf("num = %d \\n", num);
    CloseHandle(mySema);

    system("pause");




//01.信号量可以实现多个线程的卡顿现象
//02.信号量的空位原理-->0和1的原理:互斥特点
//  入职与离职原理的特点-->空位原理
//03.如何使用信号量实现一个全局变量的自增?
//  互斥类型的方式实现-->使用信号量实现线程之间的互斥现象
//04.随机数的求取方法:
//  1.原始函数
//  2.多线程的数据丢失
//05.多线程处理状态下的CPU是不会稳定的情况
//06.信号量:0代表没有空位-->线程等待状况
//  控制访问次数
//07.互斥量与信号量的区别:
//  互斥量:只能让一个线程处于运行状态
//  信号量:可以让多个线程处于运行状态,其他线程休眠
//  临界区:只能让一个线程处于运行状态
//  时间同步:
//  事件:也可以实现让多个线程处于运行状态,其他线程休眠状态
//  原子操作:操作速度最快,因为它不需要等待操作线程,几乎直接运行状态
//注:原子量的速度快在于无需让多条线程处于等待执行状态,其他线程互斥的方式
//      存在着线程等待执行的状态

程序片段(03):01.互斥.c+02.互斥读写.c
内容概要:互斥锁

///01.互斥.c
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

int static num = 6400000;

//01.全局写入锁
//  当一个线程在进行指定变量的写入操作的时候;
//  其它线程若是需要写入这个指定变量数据,那么
//  其他线程只能处于等待执行写入数据的状态
SRWLOCK gw_lock =  0 ;

static DWORD WINAPI write(void * p)
//多线程写入状态下,同一时刻只能由一条线程执行写入状态!
    AcquireSRWLockExclusive(&gw_lock);//获得独立写入锁(进入锁定状态)
    for (int i = 0; i < 100000; ++i)
    
        --num;
    
    ReleaseSRWLockExclusive(&gw_lock);//释放独立写入锁(释放锁定状态)
    return 0;


int main01(void)

    InitializeSRWLock(&gw_lock);
    HANDLE threadArr[64];
    for (int i = 0; i < 64; ++i)
    
        threadArr[i] = CreateThread(NULL, 0, write, NULL, 0, NULL);
    
    //num += 10000;//没有生效,说明互斥锁的原则是全局生效,是对所有线程生效!
    WaitForMultipleObjects(64, threadArr, TRUE, INFINITE);
    printf("num = %d \\n", num);

    system("pause");




//01.互斥锁的概念:互斥
//  如同交往一个女友之后就被锁定了
//02.互斥锁问题:
//  线程互斥:同一时刻,只能由同一个线程执行数据操作
//03.线程的互斥实现方式:
//  临界区-->互斥量-->原子操作-->事件-->信号量-->互斥锁
//04.互斥锁的创建流程:
//  全局变量:定义互斥量
//      SRWLOCK g_lock;
//  Main函数:初始化互斥量
//      InitializeSRWLock(&g_lock);
//  数据锁定:写入和读取的锁定
//  线程函数:
//      AcquireSRWLockExclusive(&g_lock);//锁定写入
//      ReleaseSRWLockExclusive(&g_lock);//锁定释放
//05.互斥锁的使用场景:
//  1.改变一个变量的时候需要锁定(防止同时读取,同时写入)
//  2.读取一个变量的时候也需要锁定(防止同时写入,同时读取)
///02.互斥读写.c
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

int num = 6400000;//待读写的数据

SRWLOCK g_lock =  0 ;//写入锁

DWORD WINAPI write(void * p)

    printf("开始写入! \\n");
    AcquireSRWLockExclusive(&g_lock);
    for (int i = 0; i < 100000; ++i)
    
        --num;
        //Sleep(10);
    
    ReleaseSRWLockExclusive(&g_lock);
    printf("结束写入! \\n");
    return 0;


DWORD WINAPI read(void * p)

    printf("读取状态! \\n");
    AcquireSRWLockShared(&g_lock);
    int i = 0;
    while (1)
    
        ++i;
        Sleep(1000);
        printf("第%d秒, num = %d \\n", i, num);//由于写入状态锁定了,因此这里的读取状态,无法读取到数据
        if (20 == i)
            break;
    
    ReleaseSRWLockShared(&g_lock);
    printf("读取结束! \\n");
    return 0;


int main02(void)

    InitializeSRWLock(&g_lock);
    CreateThread(NULL, 0, read, NULL, 0, NULL);
    HANDLE threadArr[64] =  0 ;
    for (int i = 0; i < 64; ++i)
    
        threadArr[i] = CreateThread(NULL, 0, write, NULL, 0, NULL);
    
    WaitForMultipleObjects(64, threadArr, TRUE, INFINITE);
    printf("num = %d \\n", num);

    system("pause");


//01.互斥锁的读写状态控制
//  写入的状态下不可读取,读取的状态下不可写入
//02.锁定状态,读取完成之后才进行锁定  
//03.一个资源只能锁定一次,不能锁定多次
//04.锁定-->防止冲突问题-->读取和写入的状态
//  防止同时写入和读取数据

程序片段(04):Mutex.c
内容概要:01.跨进程Mutex(发互斥)

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[100] = "haihualovefang";

int main(void)

    //01.创建互斥量"Mutex":
    //  位于内核层|Ring0层
    HANDLE myMutex = CreateMutexA(NULL, TRUE, name);
    printf("在内核层|Ring0层创建互斥量(Mutex)成功! \\n");
    char chr = getch();//实时获取单个字符
    //02.释放互斥量:
    //  相当于发出通知
    ReleaseMutex(myMutex);
    //03.关闭互斥量:
    CloseHandle(myMutex);
    system("pause");




//01.关于跨进程的驱动访问:内核对象
//  无论是Windows还是Linux都是存在互斥量说法
//02.如果是跨进程的话:
//  创建跨进程的Mutext需要有名称(便于全局访问)
//03.编写网络程序的时候:
//  既需要编写客户端也需要编写网络端
//  -->编写两个程序的时代
//04.演示的时候需要:
//  进行编译好的程序之间的演示
//05.跨进程通信:
//  1.Event&Mutex&semaphore都可以实现跨进程的线程通信
//  2.Mutex是最安全的跨进程线程访问(因为能够处理发送通知方的断开情况)
//      发出通信信息的进程退出情况能够处理!

程序片段(05):Mutex.c
内容概要:02.跨进程Mutex(收互斥)

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[100] = "haihualovefang";

int main(void)

    //01.打开互斥量:
    //  作用:获取互斥量
    //  格式:HANDLE mutex = OpenMutexA(arg1, arg2, arg3);
    //      mutex:互斥量+arg1:检索范围+arg2:继承句柄+互斥量名称
    HANDLE myMutex = OpenMutexA(MUTEX_ALL_ACCESS, TRUE, name);//获取互斥量
    //if (NULL == myMutex)//判定互斥量
    //
    //  printf("获取互斥量失败! \\n");
    //  system("pause");
    //  return;
    //
    printf("等待状态! \\n");
    //02.控制互斥量的等待时间:
    //  先获得互斥量-->设定等待状态时间(等待指定的时间范围!)
    DWORD res = WaitForSingleObject(myMutex, 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(myMutex);
    system("pause");


//01.刚才的程序特点:
//  都是出于同一个进程内的线程操作(同一进程)
//02.C++关于"事件"和"信号量"的封装:
//  封装通用的一个机制,Cocos2dx的时候都是一样的情况
//  包含OC也一样,只不过它们将接口内容进行了简化
//03.多线程的强化:
//  1.event&mutex&semaphore:(驱动层|Ring0层)
//      本质:是处于驱动里面的一个综合信号量
//  2.操作系统起到什么作用?
//      (1).操作系统类似于一个巨大的进程,里面运行的每个程序类似于线程
//          (类比:大进程&进程)<--->(进程&线程)
//      (2).电脑重启,打开多个.exe都需要重启
//      (3).操作系统和应用程序之间的关系就如同进程和线程之间的关系
//      (4).高级机制:内核对象(Ring0层对象)
//04.操作系统的高级机制:内核对象-->项目使用-->跨进程使用
//  1.操作系统的分层机制:
//      (1).ring0:就是最底层,这里可以用于编写驱动(出错:蓝屏)
//      (2).ring3:就是应用层,(出错:进程出错)
//  2.线程互斥区分机制:
//      (1).event&mutex:
//          这里创建的指针处于应用层,但是指针所指向的内存处于ring0层
//              ring0层当中的对象可以看到所有进程的内存(最高访问权限)
//      (2).进程之间不可以进行相互读写,必须通过注射方式
//      (3).event&mutex都是出于ring0层的内核对象
//          本质:对象的底层特点
//          所以:它们不仅可以用于一个进程内的线程互斥,还可以用于多个进程之间的线程互斥
//05.mutex的互斥问题解析:
//  1.跨进程的mutex互斥问题
//  2.C++的线程库都是对C语言多线程的封装
//          大概原理-->C++的类使用
//06.关于跨进程通信的问题:
//  最好使用互斥量(mutex)实现跨进程通信
//  原因:其他方式(event&semaphore)不能处理进程断开的情况!

程序片段(06):发事件.c
内容概要:01.跨进程Event(发事件)

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[100] = "haihualovefang";

//01.Event实现跨进程通信:
//  1.这儿的Event不是线程级别的含义,而是进程级别的含义:
//      该Event实质上是位于(内核|Ring0层),因此可以实现跨进程通信
//  2.参数说明:第二个参数表示是否重置手动重置事件状态
//      TRUE:手动重置+FALSE:自动重置
int main(void)

    HANDLE myEvent = CreateEventA(NULL, FALSE, FALSE, name);//创建事件
    printf("跨进程Event创建成功! \\n");
    char chr = getch();
    SetEvent(myEvent);//设置事件
    printf("发送跨进程Event事件! \\n");

    CloseHandle(myEvent);
    system("pause");




//01.严格区分跨线程和跨进程
//02.使用Event实现跨进程线程访问
//03.Event和Mutex有一定的区别:
//  Event跨进程不能使用匿名的,否则的话找不到
//注:跨进程一定要采用唯一名称标识信号
//04.TCP/UDP的时候就是如此复杂的情况
//05.一般进程与进程之间都需要设定一个超时等待时间
//06.Event天生的缺陷:
//  只有Mutex可以感知到另外一个进程的丢失
//  Event不具备感知进程丢失的功能
//注:进程通信情况之下的进程丢失情况分析!

程序片段(07):收事件.c
内容概要:02.跨进程Event(收事件)

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[100] = "haihualovefang";

int main(void)

    //01.打开事件:
    //  获取跨进程所创建的事件
    HANDLE myEvent = OpenEventA(EVENT_ALL_ACCESS, TRUE, name);//获取事件
    if (NULL == myEvent)
    
        printf("跨进程Event获取失败! \\n");
        system("pause");
        return;
    
    printf("跨进程Event等待状态! \\n");
    DWORD res = WaitForSingleObject(myEvent, 10000);
    switch (res)
    
    case WAIT_OBJECT_0:
        printf("跨进程Event收到状态! \\n");
        break;
    case WAIT_TIMEOUT:
        printf("跨进程Event超时状态! \\n");
        break;
    case WAIT_ABANDONED:
        printf("另外一个进程已经中止! \\n");
        break;
    default:
        break;
    

    CloseHandle(myEvent);
    system("pause");

程序片段(08):发信号.c
内容概要:01.跨进程Semaphore(发信号)

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[100] = "haihualovefang";

int main(void)
   
    HANDLE mySema = CreateSemaphoreA(NULL, 0, 1, name);
    printf("跨进程Semaphore信号量创建成功! \\n");
    char chr = getch();
    ReleaseSemaphore(mySema, 1, NULL);
    printf("跨进程Semaphore发出信号! \\n");

    CloseHandle(mySema);
    system("pause");




//01.当一条线程做完一件事情之后,需要通知其他线程的时候:
//  这个时候就需要进行线程之间的通信
//注:区分线程通信与进程通信
//02.大数据你就得将图论和树结构玩儿的相当好才行
//  图和树就是用于管理这么多的线程的
//03.线程与线程之间的关系是很复杂的:
//  需要掌握逻辑&排序&容错&模糊
//04.跨进程的线程通信:
//  Event&Mutex&Semaphore
//05.使用跨进程通信的时候:
//  1.最佳解决方案就是Mutex
//  2.缺点比较:
//      Event&Semaphore:发信信号的进程关闭之后无法感知到!
//      Mutex:发送信号的进程关闭之后能够被感知到!

程序片段(09):收信号.c
内容概要:02.跨进程Semaphore(收信号)

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[100] = "haihualovefang";

int main(void)

    HANDLE mySema = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, TRUE, name);
    if (NULL == mySema)
    
        printf("跨进程Semaphore创建失败! \\n");
        system("pause");
        return;
    
    printf("跨进程Semaphore等待状态! \\n");
    DWORD res = WaitForSingleObject(mySema, 10000);
    switch (res)
    
    case WAIT_OBJECT_0:
        printf("跨进程Semaphore通信收到! \\n");
        break;
    case WAIT_TIMEOUT:
        printf("跨进程Semaphore通信超时! \\n");
        break;
    case WAIT_ABANDONED:
        printf("另外一个进程已经中止! \\n");
        break;
    default:
        break;
    

    CloseHandle(mySema);
    system("pause");

程序片段(10):TimePrc.c
内容概要:时间同步

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

//01.时间同步:标准回调函数格式
//  1.小写"void"和大写"VOID"实质一样-->在这儿只是回调函数的规范
//  2.参数:普通指针+时间1[低点]+时间2[高点]-->相当于时差
//  3.创建一个回调函数格式的函数指针常量
//  4.回调函数:CALLBACK的标识定义(标准定义)
VOID CALLBACK timeRun(void * pArg, DWORD timeLow, DWORD timeHigh)

    DWORD dwindex = *(DWORD *)pArg;
    printf("第%d次! \\n", dwindex);
    MessageBoxA(0, "1", "2", 0);


//02.Win操作系统之下使用系统自带的定时器资源:
//  1.创建定时器:有几个函数-->起到等待作用的定时器
//  2.参数:arg1,arg2,arg3-->arg3是定时器的名称
//  3.匿名定时器只能有一个,携带名称的定时器可以有多个!
int main(void)

    HANDLE time1 = CreateWaitableTimerA(NULL, TRUE, "haihua");
    if (NULL == time1)
    
        printf("定时器创建失败! \\n");
    
    //设置定时器特点
    LARGE_INTEGER myTime;
    myTime.QuadPart = -50000000;//单位:0.1微妙--万分之一毫秒
    //SetWaitTimer:定义解释
    //  _In_ HANDLE hTimer;定时器
    //  _In_ const LARGE_INTEGER * 1pDueTime;//时间
    //  _In_ LONG 1Period;//循环次数
    //  _In_opt_ PTIMERAPCROUTINE pfnCompletionRoutine;//函数指针
    //  _In_opt_ LPVOID 1pArgToCompletionRoutline;//参数                   
    //  _In_ BOOL fResume;//始终恢复状态
    //设置等待的定时器(等待定时器)
    DWORD dwparam = 1;
    //1000说明1000毫秒-->1分钟干一次,回调间隔
    if (SetWaitableTimer(time1, &myTime, 1000, timeRun, &dwparam, FALSE))
    //五秒钟之后触发该事件:1|0
        printf("等待5秒之后开始干活儿! \\n");
        for (int i = 0; i < 15; ++i, ++dwparam)
        //执行次数-->循环多少次,就回调多少次
            SleepEx(INFINITE, TRUE);
        
    
    //循环完毕之后所需执行的操作:
    //  取消定时器和关闭句柄资源
    CancelWaitableTimer(time1);
    CloseHandle(time1);

    if (WAIT_OBJECT_0 == WaitForSingleObject(time1, INFINITE))
    //等待消息成功
        printf("wait ok! \\n");
    
    else
    
        printf("wait no! \\n");
    

    system("pause");




//01.多线程与队列:
//  实现文件加密
//02.关于"时间定时器"的一些操作:
//  简单定时器-->允许回调函数
//03.时间同步问题:
//  1.主要用于解决多个线程的时间问题[多线程]
//  2.围绕时间定时器,每隔一段事件干一定的活儿
//  3.满足一定的时间条件,然后解决一定的问题
//04.回调函数与时间的概念:
//  1.触发函数的动作-->回调动作
//  2.执行完一段代码之后,执行某一个函数
//05.回调函数原理:
以上是关于20160227.CCPP体系详解(0037天)的主要内容,如果未能解决你的问题,请参考以下文章

20160225.CCPP体系详解(0035天)

20160206.CCPP体系详解(0016天)

20160219.CCPP体系详解(0029天)

20160218.CCPP体系详解(0028天)

20160226.CCPP体系详解(0036天)

20160210.CCPP体系详解(0020天)