1.原子访问
原子访问指的是一个线程在访问某个资源的同时能够保证没有其他线程会在同一时刻访问同一资源。相关的Interlocker函数有如下:
1)InterlockedExchangeAdd
2)InterlockedExchangeAdd64
3)InterlockedIncrement
4)InterlockedExchange
5)InterlockedExchange64
........
Interlocker函数的工作原理: 会在总线上维护一个硬件信号,这个信号会阻止其它CPU访问同一个内存地址。
Interlocker函数的优点: 执行速度快,调用一次Interlocker函数通常只占用几个CPU周期(通常小于50),而且不需要在用户模式和内核模式之间进行切换(这个切换通常需占用1000个CPU周期以上)
应用场景: 实现旋转锁;当多个进程需对访问一个共享内存段中的值进行同步时,也可使用。
2.高速缓存行
高速缓存行是以对齐到32字节、64字节或128字节( 取决于CPU)为边界,将应用程序所访问的一组相邻字节进行缓存,以提高性能。为解决CPU间读取"脏"数据的问题,采用"观察者"的设计模式,即某个CPU修改高速缓存中的某个字节时,机器中其它的CPU会收到通知,并使自己的高速缓存行作废,重新访问内存来填充自己的高速缓存行。
应用场景: 应根据高速缓存行的大小来将应用程序的相类似的数据组织在一起,并将数据与缓存行的边界对齐。把只读数据(或不经常读的数据)与可读写数据分别存放,还应该把差不多同一时间访问的数据组织在一起。
#define CACHE_ALIGN 64
struct __declspec(align(CACHE_ALIGN)) CUSTINFO
{
DWORD dwCustomerID; //mostly read-only
wchar_t szname[100]; //mostly read-only
__declspec(align(CACHE_ALIGN))
int nBalanceDue; //Read-write
FILETIME ftLastorderDate; //Read-write
};
3.高级线程同步
这种机制实现既能让线程等待共享资源的访问权,又不会浪费CPU时间。 大致原理: 当线程想访问一个共享资源或想要得到一些特殊事件的通知时,线程必须调用操作系统的一个函数(例如: WaitForSingedObject),并将线程想要等待的东西作为参数传入,由操作系统来记住线程想要访问什么资源或想得到什么通知。
如果无法取得对共享资源的访问权(可能另一个线程正在占用),或者特殊事件尚未触发,那么系统会将线程切换到等待状态,让线程变得不可调度。
如果操作系统检测到共享资源已经可供使用了,或者特殊事件触发了,线程调用的等待函数将返回,线程变成可调度的状态。
4.关键段
关键段是一小段代码,它在执行之前需要独占对一些共享资源的访问权。
使用示例:
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);
EnterCriticalSection(&cs);
//共享资源
LeaveCriticalSection(&cs);
DeleteCriticalSection(&cs);
关键段在内部也使用Interlocker函数,执行速度快,但是无法用来在多个进程之间的同步,只能是用于同一进程内的线程进行同步,属于轻量级的。