The single-threaded version took me about two minutes.
Start by clarifying requirements and constraints, then propose a design using a single lock or atomic operations to ensure thread safety and all-or-nothing semantics. Discuss trade-offs between coarse-grained and fine-grained locking, and consider optimistic concurrency for scalability. Finally, outline implementation details and test cases for concurrency.
Pro tip: Mention that you would use a lock-free approach with atomic compare-and-swap (CAS) for high contention, but acknowledge that a simple mutex is often sufficient and less error-prone. This shows you understand both performance and maintainability.
Ask about expected concurrency level, performance requirements, and whether buy/sell operations need to be fair or can be starved. Confirm that sell must be all-or-nothing and inventory cannot go negative.
Decide between coarse-grained locking (e.g., a single mutex) and fine-grained/optimistic concurrency (e.g., atomic CAS). Discuss trade-offs: simplicity vs. scalability, and potential for contention.
Define methods like buy(int quantity) and sell(int quantity) that return success/failure or throw exceptions. Ensure sell checks available shares atomically before decrementing.
Use the chosen synchronization to protect the share count. For sell, perform a check-and-decrement atomically. For buy, simply increment atomically. Consider using a ReentrantLock or synchronized block.
Write unit tests with multiple threads to verify no negative inventory and all-or-nothing sell. Use stress tests to uncover race conditions.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.