Lazy Foo' Productions

Atomic Operations

Atomic Operations screenshot

Last Updated: Jan 10th, 2024

Semaphores operate at an operating system level. Atomic operations are a way to lock data at an efficient CPU level. Here we'll be locking a critical section using CPU spinlocks.
//Data access spin lock
SDL_SpinLock gDataLock = 0;

//The "data buffer"
int gData = -1;
Instead of a semaphore we'll be using a spinlock to protect our data buffer.
bool loadMedia()
    //Loading success flag
    bool success = true;
    //Load splash texture
    if( !gSplashTexture.loadFromFile( "48_atomic_operations/splash.png" ) )
        printf( "Failed to load splash texture!\n" );
        success = false;

    return success;

void close()
    //Free loaded images;

    //Destroy window    
    SDL_DestroyRenderer( gRenderer );
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;
    gRenderer = NULL;

    //Quit SDL subsystems
Unlike semaphores, spin locks do not need to be allocated and deallocated.
int worker( void* data )
    printf( "%s starting...\n", data );

    //Pre thread random seeding
    srand( SDL_GetTicks() );
    //Work 5 times
    for( int i = 0; i < 5; ++i )
        //Wait randomly
        SDL_Delay( 16 + rand() % 32 );
        SDL_AtomicLock( &gDataLock );

        //Print pre work data
        printf( "%s gets %d\n", data, gData );

        gData = rand() % 256;

        //Print post work data
        printf( "%s sets %d\n\n", data, gData );
        SDL_AtomicUnlock( &gDataLock );

        //Wait randomly
        SDL_Delay( 16 + rand() % 640 );

    printf( "%s finished!\n\n", data );

    return 0;
Here our critical section is protected by SDL_AtomicLock and SDL_AtomicUnlock.

In this case it may seem like semaphores and atomic locks are the same, but remember that semaphores can allow access beyond a single thread. Atomic operations are for when you want a strict locked/unlocked state.