_InterlockedDecrement intrinsic functions

Microsoft Specific

Provides compiler intrinsic support for the Win32 Windows SDK InterlockedDecrement function.


long _InterlockedDecrement(
   long * lpAddend
long _InterlockedDecrement_acq(
   long * lpAddend
long _InterlockedDecrement_rel(
   long * lpAddend
long _InterlockedDecrement_nf(
   long * lpAddend
short _InterlockedDecrement16(
   short * lpAddend
short _InterlockedDecrement16_acq(
   short * lpAddend
short _InterlockedDecrement16_rel(
   short * lpAddend
short _InterlockedDecrement16_nf(
   short * lpAddend
__int64 _InterlockedDecrement64(
   __int64 * lpAddend
__int64 _InterlockedDecrement64_acq(
   __int64 * lpAddend
__int64 _InterlockedDecrement64_rel(
   __int64 * lpAddend
__int64 _InterlockedDecrement64_nf(
   __int64 * lpAddend


[in, out] Pointer to the variable to be decremented.

Return value

The return value is the resulting decremented value.


Intrinsic Architecture
_InterlockedDecrement, _InterlockedDecrement16 x86, ARM, x64, ARM64
_InterlockedDecrement64 ARM, x64, ARM64
_InterlockedDecrement_acq, _InterlockedDecrement_rel, _InterlockedDecrement_nf, _InterlockedDecrement16_acq, _InterlockedDecrement16_rel, _InterlockedDecrement16_nf, _InterlockedDecrement64_acq, _InterlockedDecrement64_rel, _InterlockedDecrement64_nf, ARM, ARM64

Header file <intrin.h>


There are several variations on _InterlockedDecrement that vary based on the data types they involve and whether processor-specific acquire or release semantics is used.

While the _InterlockedDecrement function operates on 32-bit integer values, _InterlockedDecrement16 operates on 16-bit integer values and _InterlockedDecrement64 operates on 64-bit integer values.

On ARM platforms, use the intrinsics with _acq and _rel suffixes if you need acquire and release semantics, such as at the beginning and end of a critical section. The intrinsics with an _nf ("no fence") suffix don't act as a memory barrier.

The variable pointed to by the lpAddend parameter must be aligned on a 32-bit boundary; otherwise, this function fails on multiprocessor x86 systems and any non-x86 systems. For more information, see align.

These routines are only available as intrinsics.


// compiler_intrinsics_interlocked.cpp
// compile with: /Oi
#define _CRT_RAND_S

#include <cstdlib>
#include <cstdio>
#include <process.h>
#include <windows.h>

// To declare an interlocked function for use as an intrinsic,
// include intrin.h and put the function in a #pragma intrinsic
// statement.
#include <intrin.h>

#pragma intrinsic (_InterlockedIncrement)

// Data to protect with the interlocked functions.
volatile LONG data = 1;

void __cdecl SimpleThread(void* pParam);

const int THREAD_COUNT = 6;

int main() {
   DWORD num;
   int args[THREAD_COUNT];
   int i;

   for (i = 0; i < THREAD_COUNT; i++) {
      args[i] = i + 1;
      threads[i] = reinterpret_cast<HANDLE>(_beginthread(SimpleThread, 0,
                           args + i));
      if (threads[i] == reinterpret_cast<HANDLE>(-1))
         // error creating threads

   WaitForMultipleObjects(i, threads, true, INFINITE);

// Code for our simple thread
void __cdecl SimpleThread(void* pParam) {
   int threadNum = *((int*)pParam);
   int counter;
   unsigned int randomValue;
   unsigned int time;
   errno_t err = rand_s(&randomValue);

   if (err == 0) {
      time = (unsigned int) ((double) randomValue / (double) UINT_MAX * 500);
      while (data < 100) {
         if (data < 100) {
            printf_s("Thread %d: %d\n", threadNum, data);

         Sleep(time);   // wait up to half of a second

   printf_s("Thread %d complete: %d\n", threadNum, data);

END Microsoft Specific

See also

Compiler intrinsics
Conflicts with the x86 Compiler