首页 > 编程知识 正文

io多路复用是同步还是异步,互斥信号量mutex

时间:2023-05-06 07:13:52 阅读:116918 作者:3717

///VC、线程同步方法:排他量、信号量、原子锁定

原子锁定:如果多个线程同时操作同一资源,则线程之间的资源抢占可能会导致操作结果丢失或无法达到预期结果。

例如,线程a对一个变量执行var操作,线程b也执行var操作。 当线程a执行var时,如果线程切换时间是线程a即将在结果中存在var变量之前,则线程b继续执行var; 此时,假设var值已由线程b更新。 此时,按顺序对线程a执行,线程a继上次停止的点之后继续向下执行。 此时,b对var变量的更改将被复盖。 原子锁定是指将一个操作指令保护到原子,同时只允许一个线程操作变量,从而确保数据的正确性。

1、交互增量:加1操作;

2、联锁指令:负1操作;

3、InterlockedExchangeAdd :加上"指定"的值,可以加上负数;

4、InterlockedExchange、InterlockedExchangePointer (第一参数的值可以通过原子操作置换为第二参数的值;

一般来说,在多线程编程中,在更改某个变量的值时,使用上述互锁函数会很有用,但在多线程之间往往会操作更复杂的内容,如赋值到一个结构、插入和删除链表等,如上所述(互斥、信号量、消息队列等)

如果未使用原子锁定:

# include windows.h # includeiostreamusingnamespacestd; # definethreadnum2# definecircletime 1000000 longg _ logi ncount=0; long g_value=0; dwordwinapithreadproc1(_ inlpvoidlpparameter ) for(intindex=0; indexCIRCLETIME; 索引(g _ logi ncount; }返回0; } dwordwinapithreadproc2(_ inlpvoidlpparameter ) ) for(intindex=0; indexCIRCLETIME; 索引(g _ logi ncount; }返回0; (}int main ) ) { HANDLE handle[ ThreadNum ]={0}; handle [0]=createthread (空,0,ThreadProc1,空,0,空); handle [1]=createthread (空,0,ThreadProc2,空,0,空); witformultipleobjects (thread num,handle,TRUE,INFINITE ); closehandle(handle[0]; closehandle(handle[1]; cout '循环后的值为: ' g _ logi ncount ' ' g _ value endl; 返回0; }执行2次的结果分别如下。

循环后的值为: 1047393 0

循环后的值为: 1033066 0

使用原子锁定时:

dwordwinapithreadproc2(_ inlpvoidlpparameter ) for(intindex=0; indexCIRCLETIME; 索引(g _ logi ncount; 交互式增量(g _ value; }返回0; } dwordwinapithreadproc1(_ inlpvoidlpparameter ) for(intindex=0; indexCIRCLETIME; 索引(g _ logi ncount; 交互式增量(g _ value; }返回0; }执行2次的结果分别如下。

循环后的值为: 1028567 2000000

循环后的值为: 1326157 2000000

互斥量,信号量同步示例#definestartthread(thrFun ) closehandle (createthread ) NULL,0,thrfun,NULL,0,NULL ) ) ) ) hmutex ) int g_num=2000; DWORD W

INAPI MyThread1( LPVOID lpParam ){ while (1) { WaitForSingleObject(g_hMutex,INFINITE);//等待互斥对象有信号 if (g_num>0) { g_index++; TRACE("rn [%03d] [A] NUM=%d",g_index,g_num); g_num--; } ReleaseMutex(g_hMutex); } return 0;}DWORD WINAPI MyThread2( LPVOID lpParam ){ while(1){ WaitForSingleObject(g_hMutex,INFINITE);//等待互斥对象有信号 if (g_num>0) { g_index++; TRACE("rn [%03d] [B] NUM=%d",g_index,g_num); g_num--; } ReleaseMutex(g_hMutex); } return 0;}void CMutex_LockDlg::OnBnClickedOk(){ // TODO: 在此添加控件通知处理程序代码 g_hMutex=CreateMutex(NULL,TRUE,LPCTSTR("tickets")); if (g_hMutex) { if (ERROR_ALREADY_EXISTS==GetLastError()) { TRACE("____Create Mutex fail_____"); return; } } WaitForSingleObject(g_hMutex,INFINITE);//等待进入互斥体 INFINITE -1 ReleaseMutex(g_hMutex); ReleaseMutex(g_hMutex); StartThread(MyThread1); StartThread(MyThread2);}

信号量(Semaphore)和互斥量一样,属于内核对象。它自动执行可用资源查询的测试,如果有可用资源,则可用资源的计数减少,从而避免其它线程请求资源。当该线程释放该资源后,可用资源计数增加,则操作系统允许另一个线程请求资源。
信号量与临界区和互斥量的不同在于,它不能被认为属于某个线程。也就是说,一个线程可以等待信号量对象(减少它的资源计数),而另一个线程释放该对象(增加它的资源计数)。
Win32 API提供了几个函数用于支持信号量。使用Win32 API产生一个信号量,必须首先调用CreateSemaphore()函数,该函数描述如下:
创建一个信号量
*@param lpSemaphoreAttributes 指定安全属性,如果是NULL就表示使用默认属性。
*@param lInitialCount 用于指定该信号量的初始资源计数,必须大于或等于0,并且小于或等于lMaximumCount。
*@param lMaximumCount 指定信号量的最大资源计数。
*@param lpName 是赋给信号量的字符串名字。
HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);

你可以根据信号量的字符串名字得到该信号量的句柄:
*@param dwDesiredAccess 访问方式,同互斥量参数。
*@param bInheritHandle 继承特性,同互斥量参数。
*@param lpName 信号量名字。
HANDLE OpenSemaphore(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);

释放信号量函数:
*@param hSemaphore 信号量的句柄。
*@param lReleaseCount指信号量现值的增额,该值必须大于0。
*@param lpPreviousCount 传回信号量原来的计数,可以为NULL。
BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount);

释放信号量函数与释放互斥量函数形式相同,但不同之处在于:
一、任意线程可以在任意时刻调用此函数,因为信号量对象不为某个线程拥有。
二、ReleaseSemaphore()函数可以用大于1的大小来增加信号量的资源计数。

#include "stdafx.h"#include <stdio.h>#include <windows.h>#include <string.h>#include <stdlib.h>#define threadnum 10typedef struct THREADDATA{ int id; char name[10]; int sleep;}THREADDATA;HANDLE handleSemaphore;char * str;DWORD WINAPI ThreadProc( LPVOID lpParam ){ THREADDATA *data=(THREADDATA *)lpParam; WaitForSingleObject(handleSemaphore,INFINITE); for(int i=0;i<10;i++) { // WaitForSingleObject(handleSemaphore,INFINITE); printf("thread%d:%dn",data->id,i); // ReleaseSemaphore(handleSemaphore,1,NULL); Sleep(data->sleep); } ReleaseSemaphore(handleSemaphore,1,NULL); return 0;}int main(int argc, char* argv[]){ str=(char*)malloc(30); THREADDATA pData[threadnum]; DWORD dwThreadId[threadnum]; HANDLE hThread[threadnum]; handleSemaphore=CreateSemaphore(NULL,1, 2,"thread"); for(int i=0;i<threadnum;i++) { pData[i].id=i; sprintf(pData[i].name,"yuguoqing"); pData[i].sleep=i*10; hThread[i] = CreateThread(NULL,0,ThreadProc, pData+i, 0, dwThreadId+i); } WaitForMultipleObjects(threadnum, hThread, TRUE, INFINITE); return 0;}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。