一、线程同步
在多线程的环境中,如果没有同步机制来保证后果是不堪设想的,线程同步主要表现在两个方面,在操作系统课程中都讲过,分别是:
1、进程间互斥:使得多个线程能够共享资源而破坏资源。例如,同时有两个线程对同一个文件进行写操作,我们必须保证,在一个时间只有一个线程能够对该文件进行写操作。
2、进程间同步:进程的运行有先后关系,例如,一个线程放苹果,一个线程吃苹果,那么,只有放苹果线程运行完毕后,吃苹果线程才能运行。
按是否使用内核对象来划分,可以分为用户方式中的线程同步和线程与内核对象的同步,现在主要关注用户方式中的线程同步。
二、原子访问(互锁函数家族)
互锁函数家族可以保证进程间的互斥,即能够保证当有多个线程访问共享资源而不破坏资源。主要针对单一的加、减、赋值等简单操作。对于x86家族的CPU来说,互锁函数是通过对总线发出一个硬件信号,防止另一个CPU访问同一个内存地址来实现的。
1、 加互锁
LONG InterlockedExchangeAdd(
PLONG plAddend, //加数地址
LONG lIncrement); //被加数
2、 赋值互锁
32位赋值:
LONG InterlockedExchange(
PLONG plTarget,
LONG lValue);
64位赋值:
LONG InterlockedExchangePointer(
PLONG plTarget,
LONG lValue);
3、 条件替换互锁
32位条件替换
LONG InterlockedCompareExchange(
PLONG plDestination,
LONG lExchange,
LONG lComparand);
64位条件替换
LONG InterlockedCompareExchangePointer(
PLONG plDestination,
LONG lExchange,
LONG lComparand);
4、 自增互锁
LONG InterlockedIncrement(
PLONG plAddend);
LONG InterlockedDecrement(
PLONG plAddend);
二、 关键代码段(临界区)
关键代码段使得不同线程能够互斥的访问共享资源,但其只能用于属于同一进程中的不同线程的的互斥访问,无法完成对多个进程中的各个线程进行同步。若要针对多个进程中的各个线程需要使用内核对象同步方式。
1、所用数据结构及API
所用数据结构:CRITICAL_SECTION
所用API:
1、 初始化CRITICAL_SECTION变量
VOID InitializeCriticalSection(
CRITICAL_SECTION pcs);
2、 删除CRITICAL_SECTION变量
VOID DeleteCriticalSection
CRITICAL_SECTION pcs);
3、 上锁
VOID EnterCriticalSection(
CRITICAL_SECTION pcs);
4、 解锁
VOID LeaveCriticalSection(
CRITICAL_SECTION pcs);
2、使用方法
1、首先以全局变量或其他可以实现线程间可见的方式定义一CRITICAL_SECTION结构类型的变量。
2、对该变量进行初始化。
3、将对共享资源进行操作的代码放到上锁函数与解锁函数之间。
4、当确信不在需要该关键代码段时,清理该结构。
例:
CRITICAL_SECTION lock_section;
……
EnterCriticalSection(&lock_section);
……
LeaveCriticalSection(&lock_section);
在多线程的环境中,如果没有同步机制来保证后果是不堪设想的,线程同步主要表现在两个方面,在操作系统课程中都讲过,分别是:
1、进程间互斥:使得多个线程能够共享资源而破坏资源。例如,同时有两个线程对同一个文件进行写操作,我们必须保证,在一个时间只有一个线程能够对该文件进行写操作。
2、进程间同步:进程的运行有先后关系,例如,一个线程放苹果,一个线程吃苹果,那么,只有放苹果线程运行完毕后,吃苹果线程才能运行。
按是否使用内核对象来划分,可以分为用户方式中的线程同步和线程与内核对象的同步,现在主要关注用户方式中的线程同步。
二、原子访问(互锁函数家族)
互锁函数家族可以保证进程间的互斥,即能够保证当有多个线程访问共享资源而不破坏资源。主要针对单一的加、减、赋值等简单操作。对于x86家族的CPU来说,互锁函数是通过对总线发出一个硬件信号,防止另一个CPU访问同一个内存地址来实现的。
1、 加互锁
LONG InterlockedExchangeAdd(
PLONG plAddend, //加数地址
LONG lIncrement); //被加数
2、 赋值互锁
32位赋值:
LONG InterlockedExchange(
PLONG plTarget,
LONG lValue);
64位赋值:
LONG InterlockedExchangePointer(
PLONG plTarget,
LONG lValue);
3、 条件替换互锁
32位条件替换
LONG InterlockedCompareExchange(
PLONG plDestination,
LONG lExchange,
LONG lComparand);
64位条件替换
LONG InterlockedCompareExchangePointer(
PLONG plDestination,
LONG lExchange,
LONG lComparand);
4、 自增互锁
LONG InterlockedIncrement(
PLONG plAddend);
LONG InterlockedDecrement(
PLONG plAddend);
二、 关键代码段(临界区)
关键代码段使得不同线程能够互斥的访问共享资源,但其只能用于属于同一进程中的不同线程的的互斥访问,无法完成对多个进程中的各个线程进行同步。若要针对多个进程中的各个线程需要使用内核对象同步方式。
1、所用数据结构及API
所用数据结构:CRITICAL_SECTION
所用API:
1、 初始化CRITICAL_SECTION变量
VOID InitializeCriticalSection(
CRITICAL_SECTION pcs);
2、 删除CRITICAL_SECTION变量
VOID DeleteCriticalSection
CRITICAL_SECTION pcs);
3、 上锁
VOID EnterCriticalSection(
CRITICAL_SECTION pcs);
4、 解锁
VOID LeaveCriticalSection(
CRITICAL_SECTION pcs);
2、使用方法
1、首先以全局变量或其他可以实现线程间可见的方式定义一CRITICAL_SECTION结构类型的变量。
2、对该变量进行初始化。
3、将对共享资源进行操作的代码放到上锁函数与解锁函数之间。
4、当确信不在需要该关键代码段时,清理该结构。
例:
CRITICAL_SECTION lock_section;
……
EnterCriticalSection(&lock_section);
……
LeaveCriticalSection(&lock_section);