• Windows编程-- 用户方式中线程的同步关键代码段(临界区)


    可以从例子学习,更好的掌握

    #include <windows.h>
    #include
    <iostream.h>
    //两个线程的声明
    DWORD WINAPI Fun1Proc(LPVOID lpParameter);
    DWORD WINAPI Fun2Proc(LPVOID lpParameter);

    int tickets = 100;
    CRITICAL_SECTION g_cs;
    //定义一个临界区

    int main()
    {
    HANDLE hThread1;
    HANDLE hThread2;
    hThread1
    =CreateThread(NULL,0, Fun1Proc, NULL,0, NULL);
    hThread2
    =CreateThread(NULL,0, Fun2Proc, NULL,0, NULL);
    CloseHandle(hThread1);
    CloseHandle(hThread2);

    InitializeCriticalSection(
    &g_cs); //初始化临界区
    Sleep(4000);

    DeleteCriticalSection(
    &g_cs); //当临界区里没有资源时释放掉临界区(可以这样说吗)???

    return 0;
    }


    DWORD WINAPI Fun1Proc(LPVOID lpParameter)
    {


    while (TRUE)
    {
    EnterCriticalSection(
    &g_cs); //该线程进入临界区
    if (tickets > 0)
    {
    Sleep(
    1);
    cout
    << "Thread1 sell tickets:"<< tickets-- << endl;
    }
    else
    {
    break;
    }
    LeaveCriticalSection(
    &g_cs); //退出临界区
    }

    return0;
    }


    DWORD WINAPI Fun2Proc(LPVOID lpParameter)
    {

    while(TRUE)
    {
    EnterCriticalSection(
    &g_cs); //该线程进入临界区
    if(tickets > 0)
    {
    Sleep(
    1);
    cout
    << "Thread2 sell tickets:"<< tickets-- << endl;
    }
    else
    {
    break;
    }
    LeaveCriticalSection(
    &g_cs); //退出临界区
    }
    return 0;

    }

     应该注意的:

    1 关键代码段(临界区)工作在用 用户方式下

    2 关键代码段(临界区)是指一个小代码段,在代码够执行前。它必须独占对某些资源的访问权。

    3 关键代码段是工作在用户方式下。同步速度较快,但在使用关键代码段时,很容易进入死锁状态。因为在等待进入关键代码段时无法设定超时值。

    4 线程死锁 线程1拥有了临界区对象A。等待临界区对象B的拥有权。线程2拥有了临界区对象B,等待临界区对象A的拥有权,就造成了死锁

    5 无法用它们对多个进程中的各个线程进行同步 

     

    以下的例子就是进入了死锁。 


    #include <windows.h>
    #include
    <iostream.h>
    //1、两个线程的声明
    DWORD WINAPI Fun1Proc(LPVOID lpParameter);
    DWORD WINAPI Fun2Proc(LPVOID lpParameter);

    int tickets = 100;
    CRITICAL_SECTION g_csA;
    //2、定义两个临界区
    CRITICAL_SECTION g_csB;

    int main()
    {
    HANDLE hThread1;
    HANDLE hThread2;
    hThread1
    =CreateThread(NULL,0, Fun1Proc, NULL,0, NULL);
    hThread2
    =CreateThread(NULL,0, Fun2Proc, NULL,0, NULL);
    CloseHandle(hThread1);
    CloseHandle(hThread2);

    InitializeCriticalSection(
    &g_csA); //3、初始化临界区
    InitializeCriticalSection(&g_csB);
    Sleep(
    4000);

    DeleteCriticalSection(
    &g_csA); //4、当临界区里没有资源时释放掉临界区
    DeleteCriticalSection(&g_csB);
    return 0;
    }


    DWORD WINAPI Fun1Proc(LPVOID lpParameter)
    {

    // 11、两个临界区和两个线程会形成死机。线程在等待无法进入临界区g_csB。线程在等待无法进入临界区g_csA

    while (TRUE)
    {
    EnterCriticalSection(
    &g_csA); //5、该线程进入临界区g_csA
    Sleep(1); //6、线程进入睡眠状态 线程时间片断结束线程开始
    EnterCriticalSection(&g_csB); //9、线程进入临界区g_csB,但是临界区g_csB已被线程占用故只能等待时间片断交给线程
    if (tickets > 0)
    {
    Sleep(
    1);
    cout
    << "Thread1 sell tickets:"<< tickets-- << endl;
    }
    else
    {
    break;
    }
    LeaveCriticalSection(
    &g_csB); //退出临界区
    LeaveCriticalSection(&g_csA);
    }

    return 0;
    }


    DWORD WINAPI Fun2Proc(LPVOID lpParameter)
    {

    while(TRUE)
    {
    EnterCriticalSection(
    &g_csB); //7、线程进入临界区g_csB
    Sleep(1); //8、线程进入睡眠状态线程时间片断结束线程开始
    EnterCriticalSection(&g_csA); //10、线程进入临界区g_csA 但是临界区g_csA已被线程占用故只能等待时间片断交给线程

    if(tickets > 0)
    {
    Sleep(
    1);
    cout
    << "Thread2 sell tickets:"<< tickets-- << endl;
    }
    else
    {
    break;
    }
    LeaveCriticalSection(
    &g_csA);
    LeaveCriticalSection(
    &g_csB); //退出临界区
    }
    return 0;
    }

  • 相关阅读:
    微信小程序踩坑记
    js学习总结----同源与非同源(jsonp)
    js学习总结----crm客户管理系统之前端页面开发及数据渲染
    js学习总结----crm客户管理系统之node编写API接口
    js学习总结----crm客户管理系统之node创建服务发布项目
    js学习总结----crm客户管理系统之项目开发流程和api接口文档
    js学习总结----编写简单的ajax方法库
    js学习总结----ajax中的http请求方式及同步编程和异步编程
    js学习总结----ajax兼容处理及惰性思想
    js学习总结----http报文及ajax基础知识
  • 原文地址:https://www.cnblogs.com/fangshenghui/p/1926396.html
Copyright © 2020-2023  润新知