nextRound
TechnologiesCoding ProblemsBookmarksLearning PathsLogin
nextRound
TechnologiesCoding ProblemsBookmarksLearning PathsLogin
nextRound

AI-powered interview preparation platform. Practice with curated questions, mock interviews, and personalized learning paths to crack your dream tech interview.

Quick Links

  • Technologies
  • Mock Interviews
  • Saved Questions
  • Pricing

Company

  • About Us
  • Contact Us

Legal

  • Privacy Policy
  • Terms of Use

© 2026 nextRound. All rights reserved.

Questions
8 of 9
1How does Python's asyncio event loop achieve concurrency without using multiple threads?
2What is the difference between threading, multiprocessing, and asyncio, and when would you choose each?
3What causes a deadlock in multithreaded code, and how can it be avoided?
4Why does multiprocessing avoid the GIL problem, and what overhead does it introduce instead?
5Given the GIL, why can multithreading still improve performance for I/O-bound tasks but not CPU-bound tasks?
6What is the difference between async def and a regular function, and what does await actually do?
7How would you run CPU-bound work alongside an asyncio application without blocking the event loop?
8What is a race condition, and how would you prevent one using threading.Lock?
9What is the Global Interpreter Lock (GIL), and why does it exist in CPython?
PythonPython
Basics
Control Flow and Functions
Data Structures
Comprehensions & Functional Programming
Iterators, Generators & Decorators
Object-Oriented Programming
Exception Handling & Debugging
Concurrency & Parallelism
Performance & Optimization
Testing
Security
Modules, Packaging & Environment
Type Hinting & Modern Python
System Design & Architecture with Python
Best Practices & Design Patterns
Edge Cases & Tricky Interview Questions
08 / 09

What is a race condition, and how would you prevent one using threading.Lock?

Difficulty: 8/10
Race Conditions, Lock, Threading, Synchronization

A race is unsynchronized access to shared mutable state; a Lock serializes critical sections

A race condition occurs when the correctness of a program depends on the interleaving of operations from multiple threads, and some interleavings produce wrong results. The classic example is read-modify-write on a shared counter: counter += 1 compiles to a load, an add, and a store, and the GIL can switch between them. The GIL does not save you because it only guarantees single-bytecode atomicity, not statement atomicity. The fix is to guard the critical section with a threading.Lock: acquire before the read-modify-write and release after, using with lock: so the release happens even if an exception is raised. For simple counters, itertools.count with next() or a lock-free approach using multiprocessing.Value may be preferable depending on context.

  1. 1

    Critical section: the smallest block of code that must run without interleaving.

  2. 2

    with lock: is preferred over manual acquire/release because it guarantees release on exceptions.

  3. 3

    Other primitives: RLock for reentrant locking, Semaphore for limited concurrency, Condition for wait/notify, Event for signaling.

  4. 4

    Trade-off: locks serialize access, which reduces throughput. Keep critical sections small and avoid IO inside them.

  5. 5

    Common mistake: locking the wrong object. Locks are per-instance; two threads locking different objects do not synchronize.

  6. 6

    Common mistake: calling a function that also tries to acquire the same non-reentrant Lock and deadlocking. Use RLock when reentry is legitimate.

  7. 7

    Version note: threading.Lock is a thin wrapper over the OS primitive and is not recursive. threading.RLock is.

Scenario Questions

0-2 years experience

  1. 1Two threads increment the same counter and the final value is wrong. Why?
  2. 2What does with lock: do that acquire/release does not?

2-5 years experience

  1. 1You need to protect a shared dict from concurrent writes. What is the minimal correct approach?
  2. 2You hold a lock while making an HTTP call and latency spikes. Why and how do you fix it?

5-8 years experience

  1. 1You need to process a queue of tasks with a bounded number of concurrent workers. How do you coordinate with Semaphore and a queue?
  2. 2You have a check-then-act pattern on shared state. How do you eliminate the race without locking the world?

8+ years experience

  1. 1Design a lock-free-ish bounded producer-consumer pipeline using queue.Queue, and explain where locks are still required.
  2. 2Compare coarse-grained locking, fine-grained locking, and message passing for a high-throughput shared cache and justify a choice.

Follow-up Questions

  • Why is x += 1 not atomic despite the GIL?
  • When would you prefer a queue over a lock for coordinating threads?
Sharethis question

Share via WhatsApp, X, Facebook, LinkedIn or copy link. Open Graph preview enabled.