# (WIP) Semaphores (Examples) This page includes some examples of semaphores in multi-threading environments. The syntax is borrowed from [[EasyMT]]. ## Basic ### Synchronization Two threads `a()` and `b()` alternate their execution regardless of the scheduler. Output: `abababababab...` ```c Sem sa = 1, sb = 0; void a() { while (true) { wait(sa); printf("a") signal(sb); } } void b() { while (true) { wait(sb); printf("b"); signal(sa); } } ``` ### Critical Section & Mutex Threads **a()** and **b()** are not allowed to execute `// ... CRITICAL SECTION ...` at the same time. The issue is resolved by using a mutex semaphore. ```c Sem mutex = 1; void a() { while (true) { wait(mutex); //... CRITICAL SECTION ... signal(mutex); usleep(50); } } void b() { while (true) { wait(mutex); // ... CRITICAL SECTION ... signal(mutex); usleep(50); } } ``` ### Producer & Consumer / Bounded Buffer There is a global buffer of a bounded capacity $B$. "Producers" produce and append data to the head. They are not allowed to put more items than $B$ in the buffer. "Consumers" take and consume data from the buffer. They are not take data from the buffer if the buffer is empty. The issue is resolved by using two synchronization semaphores `full` and `empty` and one `mutex` semaphore to guard the common buffer. It is, however, possible to use two mutexes `mutex_consumer` and `mutex_producer` if the buffer is implemented in a way ```c #define B 10 /* buffer capacity */ Buffer buffer; Sem mutex = 1; Sem full = B; Sem empty = 0; void producer(int id) { while (true) { Data data = produce_data(); wait(full); wait(mutex); put_data(buffer, data) signal(mutex); signal(empty); } } void consumer(int id) { while (true) { wait(empty); wait(mutex); Data data = get_data(buffer); signal(mutex); signal(full); consume_data(data); } } ```