WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

C++ · Expert · question 66 of 100

What is a lock-free data structure, and when would you use one in C++?

📕 Buy this interview preparation book: 100 C++ questions & answers — PDF + EPUB for $5

A lock-free data structure is a data structure that can be accessed and modified concurrently by multiple threads without using locks or other synchronization primitives. Instead, it uses atomic operations and memory barriers to ensure thread-safety and consistency.

The primary advantage of lock-free data structures is that they can potentially provide higher performance than traditional lock-based data structures in highly concurrent scenarios. This is because locking and unlocking a mutex or a critical section can be an expensive operation, especially if contention is high. Lock-free data structures, on the other hand, can provide faster and more scalable access to shared resources, as multiple threads can make progress simultaneously without having to wait for a lock.

One example of a lock-free data structure is the lock-free stack. A lock-free stack is a data structure in which multiple threads can simultaneously push and pop elements onto the stack without blocking. The implementation uses atomic operations to ensure that only one thread can successfully remove an element from the stack, and that the operation is consistent and thread-safe.

Here is an example implementation of a lock-free stack using C++11’s atomic operations:

    #include <atomic>
    
    template <typename T>
    class LockFreeStack {
        public:
        LockFreeStack() : head(nullptr) {}
        
        void push(T value) {
            Node* newNode = new Node(value);
            newNode->next = head.load();
            while (!head.compare_exchange_weak(newNode->next, newNode)) {}
        }
        
        bool pop(T& result) {
            Node* oldHead = head.load();
            while (oldHead && !head.compare_exchange_weak(oldHead, oldHead->next)) {}
            if (oldHead) {
                result = oldHead->data;
                delete oldHead;
                return true;
            }
            return false;
        }
        
        private:
        struct Node {
            T data;
            Node* next;
            Node(T value) : data(value), next(nullptr) {}
        };
        
        std::atomic<Node*> head;
    };

In this implementation, the push() method creates a new node and attempts to atomically update the head pointer to point to the new node. If the update fails due to a concurrent modification, the loop retries the update until it succeeds.

The pop() method first loads the current head pointer atomically, and then attempts to update the head pointer to point to the next node. If the update fails, the loop retries the update until it succeeds. If a node is successfully removed from the stack, its data is returned and the node is deleted.

Overall, lock-free data structures can be a powerful tool in C++ for achieving high performance and scalability in concurrent applications, but they require careful design and implementation to ensure correctness and thread-safety.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic C++ interview — then scores it.
📞 Practice C++ — free 15 min
📕 Buy this interview preparation book: 100 C++ questions & answers — PDF + EPUB for $5

All 100 C++ questions · All topics