Here are some coding examples in Python, Java and C++ on how to use Semaphores and Barriers for concurrency.
- (Counting) Semaphores: allow up to number of threads to acquire the semaphore before blocking
- Barriers: Will block up to threads. When number of threads have hit the barrier, the barrier will open to allow all threads through
To showcase these in practice, I will use the Leetcode problem of
Essentially, you expose 2 functions
hydrogen()oxygen()
And you only release the molecule when 2 molecules of hydrogen and oxygen are available.
Python
from threading import Semaphore, Barrier h = Semaphore(2) b = Barrier(3) o = Semaphore(1) def hydrogen(releaseHydrogen): with h: b.wait() releaseHydrogen() def oxygen(releaseOxygen) with o: b.wait() releaseOxygen()
Java
import java.util.concurrent.*; CyclicBarrier b = new CyclicBarrier(3); Semaphore h = new Semaphore(2); Semaphore o = new Semaphore(1); void hydrogen(Runnable releaseHydrogen) throws InterruptedException { try { h.acquire(); b.await(); releaseHydrogen.run(); } catch(Exception ignore) {} finally { h.release(); } } void oxygen(Runnable releaseOxygen) throws InterruptedException { try { o.acquire(); b.await(); releaseOxygen.run(); } catch(Exception ignore) {} finally { o.release(); } }
C++
#include <semaphore.h> #include <pthread.h> pthread_barrier_t b; sem_t h; sem_t o; pthread_barrier_init(&b, 0, 3); //Need 3 threads to pass the barrier sem_init(&h, 0, 2); // Two molecules of hydrogen sem_init(&o, 0, 1); // One molecule of oxygen void hydrogen(function<void()> releaseHydrogen) { sem_wait(&h); // Two hydrogen threads can arrive at a time pthread_barrier_wait(&b); // but wait for one more thread , which must be oxygen releaseHydrogen(); sem_post(&h); } void oxygen(function<void()> releaseOxygen) { sem_wait(&o); pthread_barrier_wait(&b); releaseOxygen(); sem_post(&o); }