Here are some coding examples in Python, Java and C++ on how to use Semaphores and Barriers for concurrency.

  • (Counting) Semaphores: allow up to xx number of threads to acquire the semaphore before blocking
  • Barriers: Will block up to x1x - 1 threads. When xx number of threads have hit the barrier, the barrier will open to allow all xx 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 H2OH_2O 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); }