window下线程同步之(Critical Sections(关键代码段、关键区域、临界区域)

本文主要是介绍window下线程同步之(Critical Sections(关键代码段、关键区域、临界区域),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 关键区域(CriticalSection)

临界区是为了确保同一个代码片段在同一时间只能被一个线程访问,与原子锁不同的是临界区是多条指令的锁定,而原子锁仅仅对单条操作指令有效;临界区和原子锁只能控制同一个进程中线程的同步

使用方法:

1、初始化:InitializeCriticalSection; 
2、删除:DeleteCriticalSection; 
3、进入:EnterCriticalSection(可能造成阻塞); 
4、尝试进入:TryEnterCriticalSection(不会造成阻塞); 
5、离开:LeaveCriticalSection;

固有特点(优点+缺点):
1、是一个用户模式的对象,不是系统核心对象;
2、因为不是核心对象,所以执行速度快,有效率;
3、因为不是核心对象,所以不能跨进程使用;
4、可以多次“进入”,但必须多次“退出”;
5、最好不要同时进入或等待多个 Critical Sections,容易造成死锁;
6、无法检测到进入到 Critical Sections 里面的线程当前是否已经退出!

 

一般错误的情况:

#include <stdio.h> 
#include <windows.h>long g_nNum = 0 ; 
DWORD WINAPI ThreadProc(__in  LPVOID lpParameter); 
const int THREAD_NUM = 10;int main() 
{HANDLE  handle[THREAD_NUM];    g_nNum = 0; int var = 0; while ( var< THREAD_NUM) { handle[ var++] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);} WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);for( var=0; var<sizeof(handle); var++) { CloseHandle(handle[var]); }return 0; 
}DWORD WINAPI ThreadProc(__in  LPVOID lpParameter) 
{ Sleep(50); g_nNum++; Sleep(0); printf("当前计数为:%d\n",g_nNum); return 0; 
}

运行2次结果:

image

image

用了关键区域的情况:

#include <stdio.h> 
#include <windows.h>long g_nNum = 0 ; 
DWORD WINAPI ThreadProc(__in  LPVOID lpParameter); 
const int THREAD_NUM = 10;CRITICAL_SECTION g_ThreadCode;int main() 
{HANDLE  handle[THREAD_NUM];    g_nNum = 0; int var = 0; InitializeCriticalSection(&g_ThreadCode); while ( var< THREAD_NUM) { handle[ var++] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); } WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); DeleteCriticalSection( &g_ThreadCode ); for( var=0; var<sizeof(handle); var++) { CloseHandle(handle[var]); }return 0; 
}DWORD WINAPI ThreadProc(__in  LPVOID lpParameter) 
{  EnterCriticalSection( &g_ThreadCode ); g_nNum++;  printf("当前计数为:%d\n",g_nNum); LeaveCriticalSection( &g_ThreadCode ); return 0; 
}

image

转载于:https://www.cnblogs.com/staring-hxs/p/3664634.html

这篇关于window下线程同步之(Critical Sections(关键代码段、关键区域、临界区域)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/245690

相关文章

Spring Boot 中正确地在异步线程中使用 HttpServletRequest的方法

《SpringBoot中正确地在异步线程中使用HttpServletRequest的方法》文章讨论了在SpringBoot中如何在异步线程中正确使用HttpServletRequest的问题,... 目录前言一、问题的来源:为什么异步线程中无法访问 HttpServletRequest?1. 请求上下文与线

在 Spring Boot 中使用异步线程时的 HttpServletRequest 复用问题记录

《在SpringBoot中使用异步线程时的HttpServletRequest复用问题记录》文章讨论了在SpringBoot中使用异步线程时,由于HttpServletRequest复用导致... 目录一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源二、问题详细分

Java中将异步调用转为同步的五种实现方法

《Java中将异步调用转为同步的五种实现方法》本文介绍了将异步调用转为同步阻塞模式的五种方法:wait/notify、ReentrantLock+Condition、Future、CountDownL... 目录异步与同步的核心区别方法一:使用wait/notify + synchronized代码示例关键

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J

异步线程traceId如何实现传递

《异步线程traceId如何实现传递》文章介绍了如何在异步请求中传递traceId,通过重写ThreadPoolTaskExecutor的方法和实现TaskDecorator接口来增强线程池,确保异步... 目录前言重写ThreadPoolTaskExecutor中方法线程池增强总结前言在日常问题排查中,

Window Server创建2台服务器的故障转移群集的图文教程

《WindowServer创建2台服务器的故障转移群集的图文教程》本文主要介绍了在WindowsServer系统上创建一个包含两台成员服务器的故障转移群集,文中通过图文示例介绍的非常详细,对大家的... 目录一、 准备条件二、在ServerB安装故障转移群集三、在ServerC安装故障转移群集,操作与Ser

Window Server2016加入AD域的方法步骤

《WindowServer2016加入AD域的方法步骤》:本文主要介绍WindowServer2016加入AD域的方法步骤,包括配置DNS、检测ping通、更改计算机域、输入账号密码、重启服务... 目录一、 准备条件二、配置ServerB加入ServerA的AD域(test.ly)三、查看加入AD域后的变

Window Server2016 AD域的创建的方法步骤

《WindowServer2016AD域的创建的方法步骤》本文主要介绍了WindowServer2016AD域的创建的方法步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、准备条件二、在ServerA服务器中常见AD域管理器:三、创建AD域,域地址为“test.ly”

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后