zoukankan      html  css  js  c++  java
  • 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;
    }

  • 相关阅读:
    008——MATLAB-xlswrite的使用方法
    006——转载-MATLAB数字与字符之间的转换
    013——C# chart控件时间作为X轴(附教程)
    012——C#打开ecxel修改数据(附教程)
    010——C#选择文件路径
    011——C#创建ecxel文件(附教程)
    009——C#全局变量定义
    008——转载——c#获取当前日期时间
    007——转载——C#将字符串转换为整型的三种方法的总结
    006——C#关闭窗口 添加FormClosing事件
  • 原文地址:https://www.cnblogs.com/fangshenghui/p/1926396.html
Copyright © 2011-2022 走看看