Saturday, May 23, 2026

Class level locking in C++ - serializing multiple threads...


When I studied Android AsyncTask, especially

when Serialexecutor was the norm, I found how

Google engineers have designed to serialize

execution of multiple threads. My original

code simulating similar effects using Java

was done more than a decade ago. Here it is.


Today I did the same effect, but this time with modern C++.


Here we go.


//============================================================================

// Name : ClassLevelLockingThreadSerialization.cpp

// Author : Som

// Version :

// Copyright : som-itsolutions

// Description : Hello World in C++, Ansi-style

//============================================================================


#include <iostream>

#include <future>

#include <chrono>

#include <mutex>


class ExampleClass {

private:

static std::mutex classMutex;


public:


static void testMethod(const std::string& threadName) {


std::lock_guard<std::mutex> lock(classMutex);


for (int i = 0; i < 10; i++) {


std::cout

<< "The testMethod for "

<< threadName

<< std::endl;


std::this_thread::sleep_for(

std::chrono::seconds(1)

);

}

}

};


std::mutex ExampleClass::classMutex;


int main() {


auto f1 = std::async(

std::launch::async,

ExampleClass::testMethod,

"Thread 1"

);


auto f2 = std::async(

std::launch::async,

ExampleClass::testMethod,

"Thread 2"

);


f1.get();

f2.get();

}


Explanation


Understanding the Synchronization

The important part of the program is:

std::lock_guard<std::mutex> lock(classMutex);

This line acquires the mutex before entering the critical section. Since the mutex is declared as static, it is shared across all threads and all invocations of the method.

As a result:

  • only one thread can execute testMethod() at a time
  • the second thread waits until the first thread releases the mutex
  • thread execution becomes serialized

This is conceptually similar to Java’s static synchronized methods.

Why Use std::lock_guard?

Modern C++ prefers RAII-based locking instead of manually calling:

mutex.lock();
mutex.unlock();

std::lock_guard automatically releases the mutex when the object goes out of scope, making the code safer and exception-resistant.

Why Use std::async?

Instead of manually creating and managing std::thread objects, std::async provides a higher-level abstraction for asynchronous task execution.

Benefits include:

  • automatic thread management
  • future-based synchronization
  • cleaner code
  • safer resource handling

Final Thoughts

Modern C++ concurrency has evolved significantly from traditional thread programming. Features such as futures, mutexes, async execution, coroutines, and task systems enable developers to write safer and more scalable concurrent applications.

This small example demonstrates a foundational concept that appears everywhere in modern systems programming:

  • game engines
  • rendering systems
  • simulation frameworks
  • CAD software
  • scientific computing systems

Understanding synchronization primitives like mutexes is an important first step toward mastering advanced concurrent architectures in modern C++.

No comments: