Classical Synchronization Problems
Producer-Consumer Problem
Solving using Semaphores
# main
MAX_SIZE = 2 # buffer size
class Buffer:
def __init__(self, size):
self.buffer = [None for _ in range(size)]
self.size = size
self.fill = 0
self.use = 0
self.mutex = Semaphore(1)
# TEST if using 1 or 2 semaphores is better
def put(v):
self.mutex.wait()
self.buffer[self.fill] = v
self.fill = (self.fill + 1) % self.size
self.mutex.signal()
def get():
self.mutex.wait()
v = self.buffer[self.use]
self.use = (self.use + 1) % self.size
self.mutex.signal()
return v
buffer = Buffer(MAX_SIZE)
producerDone = Semaphore(0)
consumerDone = Semaphore(MAX_SIZE)
# Thread A
def producer():
for i in range(0, 100):
consumerDone.wait()
buffer.put(i)
producerDone.signal()
# Thread B
def consumer():
for i in range(0, 100):
producerDone.wait()
v = buffer.get()
print(v)
Solving using Conditional Variable
// main
int *buffer;
mutex_t buffer_mutex;
cond_t fill;
cond_t empty
sem_init(&buffer_mutex, 1);
// Producer
for (int i; i < 100; i++) {
mutex_lock(&buffer_mutex)
while (buffer_is_full(&buffer) {
cond_wait(&empty, &buffer_mutex)
}
put(&buffer, i)
cond_signal(&fill)
mutex_unlock(&buffer_mutex)
}
// Consumer
for (int i; i < 100; i++) {
mutex_lock(&buffer_mutex)
while (buffer_is_empty(&buffer) {
cond_wait(&fill, &buffer_mutex)
}
take(&buffer)
cond_signal(&empty)
mutex_unlock(&buffer_mutex)
}