Building H2O - Complete Solution Guide
Building H2O is LeetCode problem 1117, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
There are two kinds of threads: oxygen and hydrogen . Your goal is to group these threads to form water molecules. There is a barrier where each thread has to wait until a complete molecule can be formed. Hydrogen and oxygen threads will be given releaseHydrogen and releaseOxygen methods respectively, which will allow them to pass the barrier. These threads should pass the barrier in groups of three, and they must immediately bond with each other to form a water molecule. You must guarantee that
Detailed Explanation
The problem requires us to synchronize hydrogen and oxygen threads to form water molecules (H2O). We need to ensure that threads are released in the correct ratio (2 hydrogens and 1 oxygen) and that a full molecule is formed before the next one starts. The threads call `releaseHydrogen()` and `releaseOxygen()` respectively to indicate their readiness. The critical aspect is implementing the synchronization logic so threads wait for the necessary partners before releasing the hydrogen/oxygen.
Solution Approach
The provided solution uses semaphores to manage the availability of hydrogen and oxygen atoms, and a barrier to synchronize the threads before releasing the elements. The `hydrogen` method acquires a hydrogen semaphore, waits at the barrier, and then calls `releaseHydrogen`. The `oxygen` method acquires an oxygen semaphore, waits at the barrier, calls `releaseOxygen`, and finally releases two hydrogen semaphores and one oxygen semaphore, allowing the next water molecule to be formed.
Step-by-Step Algorithm
- Step 1: Initialize two semaphores: `h_sem` for hydrogen (initial count 2) and `o_sem` for oxygen (initial count 1). This limits the availability of hydrogen and oxygen to the correct ratio.
- Step 2: Initialize a barrier with a count of 3. This ensures that two hydrogen threads and one oxygen thread must all reach the barrier before any of them can proceed.
- Step 3: In the `hydrogen` method, acquire `h_sem`. This decrements the hydrogen count. If the count is 0, the thread waits until a hydrogen semaphore is released.
- Step 4: The `hydrogen` thread waits at the barrier using `barrier.wait()`. It blocks until two hydrogen and one oxygen thread has reached the same point.
- Step 5: The `hydrogen` thread then calls `releaseHydrogen()` after the barrier is opened.
- Step 6: In the `oxygen` method, acquire `o_sem`. This decrements the oxygen count. If the count is 0, the thread waits until an oxygen semaphore is released.
- Step 7: The `oxygen` thread waits at the barrier using `barrier.wait()`. It blocks until two hydrogen and one oxygen thread has reached the same point.
- Step 8: The `oxygen` thread calls `releaseOxygen()` after the barrier is opened.
- Step 9: The `oxygen` thread then releases two hydrogen semaphores using `h_sem.release(2)` and one oxygen semaphore using `o_sem.release()`. This makes two hydrogen and one oxygen available for the next water molecule.
Key Insights
- Insight 1: Use semaphores to control the number of available hydrogen and oxygen atoms. Initialize hydrogen semaphore with 2 and oxygen with 1 to ensure the 2:1 ratio.
- Insight 2: Employ a barrier to ensure that all three atoms (2 hydrogen, 1 oxygen) are ready before any of them proceed and release their respective elements, hence forming a molecule. This guarantees the completion of the molecule.
- Insight 3: The barrier is crucial for synchronizing the threads *after* the semaphores have been acquired, preventing a situation where the semaphores have been obtained but the threads are not yet ready to form a molecule.
Complexity Analysis
Time Complexity: O(1)
Space Complexity: O(1)
Topics
This problem involves: Concurrency.
Companies
Asked at: Rubrik, Tesla.