gist-semaphores
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| gist-semaphores [February 06, 2026 at 01:09] – yanevskiv | gist-semaphores [May 14, 2026 at 11:38] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | # (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(" | ||
| + | signal(sb); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void b() { | ||
| + | while (true) { | ||
| + | wait(sb); | ||
| + | printf(" | ||
| + | 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$. | ||
| + | |||
| + | " | ||
| + | |||
| + | " | ||
| + | |||
| + | 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, | ||
| + | | ||
| + | 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); | ||
| + | } | ||
| + | } | ||
| + | ``` | ||
