Ring3层线程同步总结

系统中全部的线程必须访问系统资源,好比堆,串口,文件,窗口以及无数其余资源。若是一个线程独占了对某个资源的访问,那么其余线程就没法完成他们的工做。另外一方面,咱们页不能让任何线程在任什么时候刻都能访问任何资源。设想有一个线程正在写入一块内存,而同时另外一个线程正在从同一块内存中读取数据,那么这个数据将变得乱七八糟,毫无用处。此时就须要线程同步。缓存

线程同步经常使用的方法:并发

1.原子访问(Interlocked系列函数):函数

必须保证传给这些函数的变量地址是通过对齐的,不然这些函数可能会失败。优化

优势:执行速度极快,不须要在用户模式和内核模式之间进行切换。ui

缺点:只能对一个数进行操做。spa

LONG InterlockedIncrement(PLONG plAddend);//plAddend增长1

LONG InterlockedDecrement(PLONG plAddend);//减少1
LONG InterlockedExchange(PLONG volatile plTarget,LONG lValue);//32位,用value替换Target,返回以前的值

LONGLONG InterlockedExchange64(PLONG volatile plTarget,LONGLONG lValue);//64位

PVOID InterlockedExchangePointer(PVOID* volatile ppvTarget,PVOID pvValue);//x86下是32位,x64下是64位

LONG InterlockedExchangeAdd(PLONG volatile plAddend,LONG lIncrement);//Addend增长Increment
LONGLONG InterlockedExchangeAdd64(PLONGLONG volatile pllAddend,LONGLONG llIncrement);

PLONG INterlockedCompareExchange(PLONG plDestination,LONG lExchange,LONG lComparand);//函数会将Destination当前值与参数Comparand的值进行比较,若是相等则替换为Comparand的值,返回初始值

LONG InterlockedCompareExchangePointer(PVOID* ppvDestination,PVOID pvExchange,PVOID pvComparand);

volatile关键字:告诉编译器这个变量可能会被应用程序以外的其余东西修改,好比操做系统、硬件或者一个并发执行的线程。确切的说,volatile限定符告诉编译器不要对这个变量进行任何形式的优化,而是始终从变量在内存中的位置读取变量的值。操作系统

 

2.关键段(Critical Section):是一段代码,它在执行以前须要独占对一些共享资源的访问权。线程

优势:容易使用,内部运用Interlocked函数执行速度很快。code

缺点:没法在多个进程之间对线程进行同步(其实Ring3的同步方式都没法在多个进程之间不一样线程同步)blog

使用方法:

CRITICAL_SECTION g_cs;//定义为全局
//使用以前先初始化
InitializeCriticalSection(&g_cs);
EnterCriticalSection(
&g_cs); .......do Some Things..... LeaveCriticalSection(&g_cs);
//使用完清理cs结构
DeleteCriticalSection(&g_cs);

任何须要访问共享资源的代码,都必须包含在EnterCriticalSection和LeaveCriticalSection之间。

若是共享资源在使用中,则EnterCriticalSection就会使线程处于等待状态,可使用下面函数,这个函数会判断资源是否在使用,若是使用中则直接返回,不会将线程切换到等待状态。

BOOL TryEnterCriticalSection(PCRITICAL_SECTION pcs);

 

3.Slim读/写锁:读写锁目的和关键段相同,对一个资源进行保护不让其余线程访问它。可是读写锁容许咱们区分那些想要读取资源的线程和写入资源的线程。

void InitializeSRWLock(PSRWLOCK SRWLock);//使用以前初始化读写锁
void AcquireSRWLockExclusive(PSRWLOCK SRWLock);//写入者线程获取锁
void ReleaseSRWLockExclusive(PSRWLOCK SRWLock);//写入者线程释放锁

//读取者线程
void AcquireSRWLockShared(PSRWLOCK SRWLock);
void ReleaseSRWLockShared(PSRWLOCK SRWLock);

//不须要删除或者销毁SRWLOCK的函数,系统会自动执行清理工做

与关键段的区别:1.读写锁不存在TryEnter*的函数,若是锁已经被占用,那么获取锁就会致使线程等待;

        2.不能递归得到SRWLOCK,也就是说,一个线程不能为了屡次写入资源而屡次锁定资源,而后在屡次调用ReleaseSRWLock*来释放对资源的锁定。

 

补充知识:

高速缓存行:当CPU从内存中读取一个字节的时候,它并不仅是从内存中取回一个字节,而是取回一个高速缓存行。高速缓存行可能包含32字节,64字节甚至是128字节(取决于CPU)。在多CPU的机器上当一个CPU修改了高速缓存行的一个字节时,机器中的其余CPU会受到通知,并使本身的高速缓存行做废。

加入条件变量的锁:

BOOL SleepConditionVariableCS(  PCONDITION_VARIABLE pConditionVariable,  PCRITICAL_SECTION pCriticalSection,
  DWORD dwMilliseconds);
BOOL  SleepConditionVariableSRW(
  PCONDITION_VARIABLE pConditionVariable,
  PSRWLOCK pSRWLock,
  DWORD dwMilliseconds,
ULONG Flags);

VOID WakeConditionVariable(
  PCONDITION_VARIABLE ConditionVariable);
VOID WakeAllConditionVariable(
  PCONDITION_VARIABLE ConditionVariable);
相关文章
相关标签/搜索