windows 核心编程之8 用户模式下的线程同步
来源:互联网 发布:工作计划软件 编辑:程序博客网 时间:2024/06/04 23:50
用户模式下的线程同步
有下面2种情况,需要用到线程同步
1 需要让多个线程同时访问一个资源,同时不能破坏资源的完整性
2 一个线程需要通知另外一个线程,任务完成。
1 原子访问方式:
提供下面以下的原子方式访问的函数:
#include <Windows.h>#include <stdio.h>int main(){// 原子方式操作LONG volatile ivVariable = 10;LONGLONG volatile llVariable = 10;// return initial value of first parameter// you can use it to do subtraction, first parameter negativeLONG ltestVar = InterlockedExchangeAdd(&ivVariable, 1);LONGLONG llTestVariable = InterlockedExchangeAdd64(&llVariable, 2);//BOOL volatile bTest = FALSE;BOOL bOldValue = (BOOL)InterlockedExchange((LONG volatile*)&bTest, TRUE);volatile int*p = new int(10);LONG* lptest = new LONG(100);LONG* plvalue = (LONG*)InterlockedExchangePointer(&p,lptest);delete p;delete lptest;LONG volatile lvolatileCompateValue = 10;// function 参数1与参数3是否相等,不相等不执行操作,//相等时,把参数2赋值给参数1,返回值参数1以前的值LONG lOldValue = InterlockedCompareExchange(&lvolatileCompateValue, 15, 11);// 参数1 是一个指针LONG volatile* lpvolatile = new LONG(11);LONG* lp = new LONG(11);LONG* lOldCompateValue =(LONG*) InterlockedCompareExchangePointer((volatile PVOID*)&lpvolatile,(PVOID)lp,(PVOID)lpvolatile);return 0;}
下面是原子访问的链表栈
#include <Windows.h>#include <stdio.h>#include <tchar.h>// 原子方式访问单向链表typedef struct mydata{int i;TCHAR ch[10];double dou;}LISTDATA;typedef struct _Slist_item{SLIST_ENTRY m_entry;LISTDATA m_data;}LISTTIME,*PLISTTIME;int main(){SLIST_HEADER head;SLIST_ENTRY slistEntry;LISTTIME ltem;PLISTTIME pLitem = NULL;InitializeSListHead(&head);for (int i = 0; i< 10; i++){pLitem = new LISTTIME;pLitem->m_data.i = i;pLitem->m_data.dou = 100;_tcscpy_s(pLitem->m_data.ch,10,TEXT("asdf"));InterlockedPushEntrySList( &head, &pLitem->m_entry );}LONG lSize = QueryDepthSList(&head);for (int i = 0; i < 10; ++i){pLitem = (PLISTTIME)InterlockedPopEntrySList(&head);delete pLitem;}InterlockedFlushSList(&head);return 0;}
2 高速缓存行
Windows SDK 代码最后释放内存有错,buffer指针移动了,下面的代码,已经改好,增加了一些新信息
#include <windows.h>#include <malloc.h> #include <stdio.h>#include <tchar.h>typedef BOOL (WINAPI *LPFN_GLPI)( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);int _cdecl _tmain (){BOOL done;BOOL rc;DWORD returnLength;DWORD procCoreCount;DWORD byteOffset;PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer, FreeBuffer;LPFN_GLPI Glpi;Glpi = (LPFN_GLPI) GetProcAddress(GetModuleHandle(TEXT("kernel32")),"GetLogicalProcessorInformation");if (NULL == Glpi) {_tprintf(TEXT("GetLogicalProcessorInformation is not supported.\n"));return (1);}done = FALSE;buffer = NULL;returnLength = 0;while (!done) {rc = Glpi(buffer, &returnLength);if (FALSE == rc) {if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {if (buffer) free(buffer);FreeBuffer = buffer=(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength);if (NULL == buffer) {_tprintf(TEXT("Allocation failure\n"));return (2);}} else {_tprintf(TEXT("Error %d\n"), GetLastError());return (3);}} else done = TRUE;}procCoreCount = 0;byteOffset = 0;while (byteOffset < returnLength) {switch (buffer->Relationship) {case RelationProcessorCore:procCoreCount++;break;case RelationNumaNode:printf("节点信息:\n");printf("numaNode = %d\n",buffer->NumaNode.NodeNumber);break;case RelationCache:printf("CPU 高速缓冲区\n");printf("关联性 %d\n",buffer->Cache.Associativity);printf("Cache %d 缓存\n",buffer->Cache.Level);printf("Cache %d 缓存行\n",buffer->Cache.LineSize );printf("Cache %dKB 大小\n", buffer->Cache.Size / 1024);switch(buffer->Cache.Type){case CacheData:printf("CacheData\n");break;case CacheInstruction:printf("CacheInstruction\n");break;case CacheTrace:printf("CacheTrace\n");break;case CacheUnified:printf("CacheUnified\n");break;}break;case RelationProcessorPackage:printf("RelationProcessorPackage:\n");break;default:break;}byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);buffer++;printf("=========================================================\n");}_tprintf(TEXT("Number of active processor cores: %d\n"), procCoreCount);free (FreeBuffer);return 0;}
3 高级线程同步
不要使用旋转锁的方式来,线程之间同步
4 关键段
CRITICAL_SECTION 是关键段的结构体,我们不需要了解结构体的细节,帮助文档也没有它的说明.
下面是初始化关键段得函数,参数是结构体地址
InitializeCriticalSection(&cs);
DeleteCriticalSection(&cs); 这个函数是删除,关键段结构体,必须成对使用,否则资源泄露
EnterCriticalSection(&cs);
//需要保护的资源
LeaveCriticalSection(&cs);
//需要保护的资源
LeaveCriticalSection(&cs);
也必须要成对使用
可以使用 TryEnterCriticalSection 来替换 EnterCriticalSection 这个函数会尝试请求资源,如果没有资源,返回false,有资源返回true,同时会更新关键段结构体,所以访问了资源后,可以调用 LeaveCriticalSection。 下面的代码说明情况了。
if(TryEnterCriticalSection(&cs))
{
//需要保护的资源
LeaveCriticalSection(&cs);
}
else
{
//没有资源可以访问
//不需要调用 LeaveCriticalSection;
}
{
//需要保护的资源
LeaveCriticalSection(&cs);
}
else
{
//没有资源可以访问
//不需要调用 LeaveCriticalSection;
}
下面的代码介绍了怎么使用关键段
#include <Windows.h>#include <stdio.h>#include <tchar.h>#include <process.h>class MyCriticalSection{public:MyCriticalSection(){InitializeCriticalSection(&m_cs);}~MyCriticalSection(){DeleteCriticalSection(&m_cs);}void Lock(){EnterCriticalSection(&m_cs);}void UnLock(){LeaveCriticalSection(&m_cs);}BOOL TryLock(){return TryEnterCriticalSection(&m_cs);}void TryUnLock(){UnLock();}private:CRITICAL_SECTION m_cs;};int gSum = 0;MyCriticalSection criticalsection;unsigned int WINAPI ThreadFuncOne(LPVOID lparam){criticalsection.Lock();for (int i = 0; i < 100; ++i){gSum++;}criticalsection.UnLock();return 0;}unsigned int WINAPI ThreadFuncTwo(LPVOID lparam){criticalsection.Lock();for (int i = 0; i < 100; ++i){gSum++;Sleep(10);}criticalsection.UnLock();return 0;}unsigned int WINAPI ThreadFuncThree(LPVOID lparam){while(!criticalsection.TryLock()){printf("没有资源可以使用\n");Sleep(10);}printf("资源可以使用\n");for (int i = 0; i < 100; ++i){gSum++;}criticalsection.TryUnLock();return 0;}int main(int argc, char **argv){HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, ThreadFuncOne, NULL, 0, NULL);HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, ThreadFuncTwo, NULL, 0, NULL);HANDLE hThread3 = (HANDLE)_beginthreadex(NULL, 0, ThreadFuncThree, NULL, 0, NULL);HANDLE harray[3] = {hThread1,hThread2,hThread3};WaitForMultipleObjects(_countof(harray),harray,TRUE,INFINITE);printf("sum = %d\n", gSum);system("pause");return 0;}
初始化的时候可以使用
//初始化的时候,使用旋转锁 单CPU上没有作用
WINBASEAPIBOOL
WINAPI
InitializeCriticalSectionAndSpinCount(
__out LPCRITICAL_SECTION lpCriticalSection,
__in DWORD dwSpinCount
);
SetCriticalSectionSpinCount 设置旋转锁的次数,单CPU没有效果,这个函数是没有使用上面那个函数,初始化关键段,在后期使用中,可以使用下面这个函数,来改变!
- windows 核心编程之8 用户模式下的线程同步
- Windows核心编程:用户模式下的线程同步
- windows 核心编程(用户模式下的线程同步)
- Windows核心编程:用户模式下的线程同步
- Windows核心编程笔记 用户模式下的线程同步
- windows核心编程-8.用户模式下的线程同步
- windows核心编程-用户模式下的线程同步1
- windows核心编程用户模式下的线程同步
- windows核心编程---用户模式下的线程同步
- Windows核心编程之 用户模式下的线程同步 读写锁和条件变量
- (摘自windows核心编程之用户模式下的线程同步)
- 《Windows核心编程》第8章 用户模式下的线程同步
- 《Windows核心编程》第8章 用户模式下的线程同步
- Windows核心编程——第8章 用户模式下的线程同步
- Windows核心编程 线程基础 线程调度、优先级、关联性 用户模式下的线程同步
- Windows核心编程:(五)用户模式下线程同步
- 【Windows核心编程学习笔记】用户模式下的线程同步之二---关键段(critical section)
- Windows核心编程学习笔记 第二部分 完成编程任务 第8章 用户模式下的线程同步
- 微信公众平台申请消息接口–struts2(jsp)
- oracle包dbms_job的使用
- 《UNIX网络编程——Socket Networking API》(3rd,Vol1)读书笔记(1)【第一章】
- JavsScript变量作用域的小发现
- 【生活随笔】随笔一
- windows 核心编程之8 用户模式下的线程同步
- mysql 主从复制
- 《Cpp primer》4th 翻译有误的一个地方
- 一.顺序存储线性表
- Android 压缩解压zip文件
- 简单的深度搜索--素环问题
- 动态MBean:DynamicMBean
- 改变Apache端口等配置修改方法
- SecurityException: java.lang.SecurityException