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

#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;
}

转载于:https://www.cnblogs.com/fangshenghui/archive/2011/01/05/1926396.html

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

  1. Windows核心编程 第八章 用户方式中线程的同步(上)

    第8章 用户方式中线程的同步 当所有的线程在互相之间不需要进行通信的情况下就能够顺利地运行时, M i c r o s o f t Wi n d o w s的运行性能最好.但是,线程很少能够在所有的时 ...

  2. 用户方式中线程的同步——Windows核心编程学习手札之八

    用户方式中线程的同步 --Windows核心编程学习手札之八 系统中所有线程都必须拥有对各种系统资源的访问权,这些资源包括内存堆栈.串口.文件.窗口和许多其他资源.如果一个线程需要独占对资源的访问权, ...

  3. Windows核心编程 第八章 用户方式中线程的同步(下)

    8.4 关键代码段 关键代码段是指一个小代码段,在代码能够执行前,它必须独占对某些共享资源的访问权.这是让若干行代码能够"以原子操作方式"来使用资源的一种方法.所谓原子操作方式,是 ...

  4. 第八章 用户方式中线程的同步(2)

    二.高级线程同步 如果线程访问共享资源或者等待一些特殊事件的发生,如果共享资源可用或特殊事件已发生则函数返回同时该进程保持可调度状态,否则该线程处于等待状态.系统将处于等待状态的线程不占用系统资源(不 ...

  5. 线程同步--关键代码段(三)

    前面讲述了如何使用关键代码段. 但是关键代码段还有一些不为人知的秘密,也是多数程序员忽略的东西,特别是在多核cpu上面,我们必须知道的东西. 下面是<windows核心编程>这本书里面的一 ...

  6. 线程同步--关键代码段(一)

    线程同步有四种方式 但是在一个进程中,效率最高的,方式是 :关键代码段 #include <iostream> #include <windows.h> #include &l ...

  7. windows编程点滴(四)之线程的同步

    MSDN -- Synchronization Functions 1. 使用临界区对象(CRITICAL_SECTION) 创建线程 unsigned long _beginthreadex(voi ...

  8. 线程同步--关键代码段(二)

    在我们接触到的多线程书籍里面,提到最多的就是线程同步问题了. 但是,我们看到最多的例子也是对一个临界资源的访问. 但是当我们自认为感觉靴子很好的时候,问题出现了,怎么才能够使我们让线程按照一定的顺序访 ...

  9. 线程同步之关键代码段

    关键代码段: 1) 关键代码段(临界区)工作在用户方式下. 2) 关键代码段(临界区)是指一个小代码段,在代码能够执行前,它必须独占对某些资源的访问权. 用InitializeCriticalSect ...

最新文章

  1. SWideRNet:全景分割新标杆!
  2. PPT插入文本框但是字体并不是想要的
  3. Scala中Manifest、ClassTag、TypeTag的学习
  4. mysql util_关于mysql数据库操作工具类MySQLUtils用于连接数据提交sql脚本及结果转为JSONArray等操作...
  5. DOS 中for遍历文件内容
  6. Java多线程之Semaphore用法
  7. 何谓CRT,CRT的由来
  8. mac mysql not found_mac下mysql提示command not found解决
  9. html高度随宽度编号,纯css实现容器高度随宽度等比例变化的四种解决方案
  10. 【计算机网络】URI、URL、URN 辨析
  11. pca 累积方差贡献率公式_PCA--主成分分析
  12. eigrp 负载均衡和非负载均衡实验
  13. HDU - 2087 剪花布条(kmp)
  14. johnson 算法 贪心
  15. VR全景图书馆让读者享受到优质的图书阅览服务
  16. 用matlab求带参数d积分,用MATLAB求定积分
  17. Modern C++ JSON nlohmann::json 使用详解
  18. 咸鱼的 Github 情报 | 一个支持边下边播、无版权限制和自动上传的BT离线下载程序...
  19. 全球最奢侈的运动品牌中国十大顶级学生儿童平衡自行车品牌排行榜
  20. truffle填坑指南:truffle unbox react项目npm run start启动失败

热门文章

  1. PYthon3:函数实现“自动售卖机”功能
  2. 解决nginx负载均衡高可用keepalived只针对物理机的问题
  3. 过程作为黑箱抽象——《计算机程序的构造和解释》
  4. 《构建之法》读书笔记
  5. 密码强弱度检测万能插件
  6. 阿里云文件存储NAS跨账号挂载
  7. POSTMAN 数据关联
  8. 导出excel表格,前端和后台导出
  9. [原创]教你如何最快写出酷炫的dialog对话框
  10. Facebook市值赶超股神巴菲特公司 全美排名第五