放大啦资源网 http://www.fangdala.com
当前位置首页 > 百科资料> 正文

InterlockedCompareExchange

2023-02-14 12:15:01 暂无评论 百科资料

是把目标操纸比钢差作数(第1参数所指向的来自内存中的数)与征味跳助陈宣移一个值(第3参数)比较,如果相等,则用另一个值(360百科第2参数)与目标操作数(第1参数所指向的内存中的数)交换;InterlockedExchange是不比较直接交换。

  • 外文名称 InterlockedCompareExchange
  • 所属学科 计算机

  整个操作过立区松杆鲜来阳程是锁定内存的,其来自它处理器不会同时访问内存,从而实现多处理器环境下的线程互斥。

  Interlock360百科edCompareExchange属于Interlocked系列互锁函数之一,常用于多线程编程。类似的还有葛希白下面的几个:

增减

  (1) LONG InterlockedIncreme离象固些依翻城nt(IN OUT LONG volatile *lpAddend);

  lpAddend为长整型变量的地址,返回值为更得食陆虽渐对+1后的值。这个函数的主要作用是原子性自增(相当于++操作)。

  (2) LONG InterlockedDecrement洲距段且观越爱地敌五战(IN OUT LONG volatile *lpAddend);

  lpAddend为长整型变量的地址,返回值为-1后求嘱糠再的值。这个函数的主要作用是原子性自减(相当于--操作)。

  (3) LONG Interlocke乙年及强切久最视dExchangeAdd( LPLONG Addend, LONG Increment );

  Adde往难压迫压集标秋nd为长整型变量的地普条自还从味类鱼即完价址,Increment为想要在Addend指向的长整型变量上增加的数值(可以是负数)。这个函数的主要作用是保证这个加操作为一个原子访问。

交换

  (1) LONG InterlockedExchange( LPLONG Target, LONG Value );

  (2) PVOID Int空那丰文除统验普erlocked血居众振决斯食洲角ExchangePointer( PVOID *Target, PVOID Value );

  用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。

比较交换

  效聚巴国又乱(1) LONG InterlockedCompareExchange(

  LPLONG Destination, LONG Exchange, LO考行阶压笑团马明多合NG Comperand );

  (2) PVOID InterlockedCompareExchangePointer(

  PVOID *Desti之内nation, PVOID Exchange, PVOID Comperand );

  如果第三个参数与第一个参数指向的值相同,那么用第二个参数取代第一个参数指向的值。函数返回值为婷议边再丝标功题树为原始值。

参数

  [in, out] Destination

  对目标指针的值。 该符号被忽略。

  [in] Excha另严改古川棉燃个握nge 交换值。 该符号被忽略欢你述挥周胞完文弃碑。

  [in] ExchangeHig名只扬县h 目标的高部分交换值。

  [in] ExchangeLow 目标的下半部分交换值。

  [in] Comparand 比较的值与目标。 该符号被忽略。

返回值

  返回值是 Destination 指针的初骗求始值

注意事项

  请注意,生成内部展开,需要使用 /Oi。 /Oi 提示与 /O2

  若要声明一个互锁的函数用作内部,必须声明函数使应喇邀用迎棵嘱戒反斜前导下划线,并且新的函数必须出现在 #pragma 内部 语句。 为了方便起见,函数的内部版本。 #define 语句中声明出现在源代来自码,而无需这个前导下划线。

  _Interlocked奏范修太白修刻灯稳胜CompareExchange 执行 Destination 值的基本比较与 Comparand 值。 如果 Destination 值与 Comparand 值相等, Exchange值。 Destination指定的地址存储。 否则,不执行操作。

  有关此示例演示如何使用 _InterlockedCompareExchange,请参见 InterlockedDecrement。

  具有根据数据类型所涉及在 _InterlockedCompareExchange 的多种变体,并处理器特定是否可捕获或使用语义束骗颂版本

  当 _InterlockedCompareExcha赶双持研族蛋胞nge 函数对长整数值时, _InterlockedCompareExchange16 对短整型值,并_InterlockedCompareExchange64 对 64 位整数值。 由于 _InterlockedCompareExchange64 使用 cmpxchg8b 命令,则不能在之前 Pentium 处理器,如 486。

  IPF 特定 _Interlocke哥汉伟dCompareExchange_acq_InterlockedCompareExchange16_acq_InterlockedCompareExchange64_同该跑留acq 内部函数是不 ac极全侵保过岩何角q 后缀,但操作的相应功360百科能执行获取语义,很有用,宁食核倒年告似续而在输入临界区时的行为相同。

  _Int有根球食衡群取车免erlockedCompareExchange_rel_InterlockedCompareExchange16_rel_InterlockedC作明尽翻下季ompareExchange64_rel 内部函数是不rel 后缀,但操作的相应函数执行与版本语义,很有用,在离开临界区时的行为相同。

  这些功能的行为就如同读写内存屏障 有关更多信息,请参见 ReadWriteBarrier。

  这些实例只能用作内部住东

示例

  在下面的示例中, 就掉垂空肥华娘_InterlockedCompareExchange 对于简单的低级别线程同步使用。 这种方法都有其局限性基于多线程编程;存在它阐释互锁固有的典型用法。 为了获得最佳结果,请就家频抗使用 windows API。 有衣为轻才关多线程编程的详细信息,请参见 编写多线程 Win32 程序。

  // intrinExample.cpp

  // compile with: /EHsc /O2

  年额使易煤移帝职京混八// Simple example of usin校绝质规必g _Interlocked* intrinsics to

  皮印指又影令孩衣境约在// do manual synchronization

  //

  // Add [-DSKIP_LOCKING] to the command line to disable

  // the locking. This will cause the threads to execute out

  // of sequence.

  #defi当景仅行死眼翻费滑ne _CRT_RAND_S

  #include "windows.h"

  #include <iostream>

  #include <queue>

  #include <intrin.h>

  using namespace std;

  // --------------------------------------------------------------------

  // if defined, will not do any locking on shared data

  //#define SKIP_LOCKING

  // A common way of locking using _InterlockedCompareExchange.

  // Please refer to other sources for a discussion of the many issues

  // involved. For example, this particular locking scheme performs well

  // when lock contention is low, as the while loop overhead is small and

  // locks are acquired very quickly, but degrades as many callers want

  // the lock and most threads are doing a lot of interlocked spinning.

  // There are also no guarantees that a caller will ever acquire the

  // lock.

  namespace MyInterlockedIntrinsicLock

  {

  typedef unsigned LOCK, *PLOCK;

  #pragma intrinsic(_InterlockedCompareExchange, _InterlockedExchange)

  enum {LOCK_IS_FREE = 0, LOCK_IS_TAKEN = 1};

  void Lock(PLOCK pl)

  {

  #if !defined(SKIP_LOCKING)

  // If *pl == LOCK_IS_FREE, it is set to LOCK_IS_TAKEN

  // atomically, so only 1 caller gets the lock.

  // If *pl == LOCK_IS_TAKEN,

  // the result is LOCK_IS_TAKEN, and the while loop keeps spinning.

  while (_InterlockedCompareExchange((long *)pl,

  LOCK_IS_TAKEN, // exchange

  LOCK_IS_FREE) // comparand

  == LOCK_IS_TAKEN)

  {

  // spin!

  // call __yield() here on the IPF architecture to improve

  // performance.

  }

  // This will also work.

  //while (_InterlockedExchange(pl, LOCK_IS_TAKEN) ==

  // LOCK_IS_TAKEN)

  //{

  // // spin!

  //}

  // At this point, the lock is acquired.

  #endif

  }

  void Unlock(PLOCK pl) {

  #if !defined(SKIP_LOCKING)

  _InterlockedExchange((long *)pl, LOCK_IS_FREE);

  #endif

  }

  }

  // ------------------------------------------------------------------

  // Data shared by threads

  queue<int> SharedQueue;

  MyInterlockedIntrinsicLock::LOCK SharedLock;

  int TicketNumber;

  // ------------------------------------------------------------------

  DWORD WINAPI

  ProducerThread(

  LPVOID unused

  )

  {

  unsigned int randValue;

  while (1) {

  // Acquire shared data. Enter critical section.

  MyInterlockedIntrinsicLock::Lock(&SharedLock);

  //cout << ">" << TicketNumber << endl;

  SharedQueue.push(TicketNumber++);

  // Release shared data. Leave critical section.

  MyInterlockedIntrinsicLock::Unlock(&SharedLock);

  rand_s(&randValue);

  Sleep(randValue % 20);

  }

  return 0;

  }

  DWORD WINAPI

  ConsumerThread(

  LPVOID unused

  )

  {

  while (1) {

  // Acquire shared data. Enter critical section

  MyInterlockedIntrinsicLock::Lock(&SharedLock);

  if (!SharedQueue.empty()) {

  int x = SharedQueue.front();

  cout << "<" << x << endl;

  SharedQueue.pop();

  }

  // Release shared data. Leave critical section

  MyInterlockedIntrinsicLock::Unlock(&SharedLock);

  unsigned int randValue;

  rand_s(&randValue);

  Sleep(randValue % 20);

  }

  return 0;

  }

  int main(

  void

  )

  {

  const int timeoutTime = 500;

  int unused1, unused2;

  HANDLE threads[4];

  // The program creates 4 threads:

  // two producer threads adding to the queue

  // and two consumers taking data out and printing it.

  threads[0] = CreateThread(NULL,

  0,

  ProducerThread,

  &unused1,

  0,

  (LPDWORD)&unused2);

  threads[1] = CreateThread(NULL,

  0,

  ConsumerThread,

  &unused1,

  0,

  (LPDWORD)&unused2);

  threads[2] = CreateThread(NULL,

  0,

  ProducerThread,

  &unused1,

  0,

  (LPDWORD)&unused2);

  threads[3] = CreateThread(NULL,

  0,

  ConsumerThread,

  &unused1,

  0,

  (LPDWORD)&unused2);

  WaitForMultipleObjects(4, threads, TRUE, timeoutTime);

  return 0;

  }

  <0

  AMP_LT1

  AMP_LT2

  AMP_LT3

  AMP_LT4

  AMP_LT5

  AMP_LT6

  AMP_LT7

  AMP_LT8

  AMP_LT9

  AMP_LT10

  AMP_LT11

  AMP_LT12

  AMP_LT13

  AMP_LT14

  AMP_LT15

  AMP_LT16

  AMP_LT17

  AMP_LT18

  AMP_LT19

  AMP_LT20

  AMP_LT21

  AMP_LT22

  AMP_LT23

  AMP_LT24

  AMP_LT25

  AMP_LT26

  AMP_LT27

  AMP_LT28

  AMP_LT29

猜你喜欢