1

I'm trying to implement mutual exclusion using semaphore in Python. The two processes (proc1, proc2) are supposed to be two independent, concurrent processes. They do exactly the same thing: store n in array[n], then increment n.

The purpose of the program is to show that using semaphore we can ensure that the array is filled properly: [0,1,2,3,4,5,6,7,8,9], without skipping any index. However, my code seems to store [0,1,0,0,0,0,0,0,0,0]. I haven't used threads in python before, so I don't know what's going on.

import threading
import time

n = 0
array = [0]*10
sem = threading.Semaphore()

def proc1():
  global n, array
  while True:
    sem.acquire()
    array[n] = n
    n += 1
    sem.release()
    time.sleep(0.25)

def proc2():
  global n, array
  while True:
    sem.acquire()
    array[n] = n
    n += 1
    sem.release()
    time.sleep(0.25)


t = threading.Thread(target = proc1)
t.start()
t2 = threading.Thread(target = proc2)
t2.start()

print (array)

2 Answers 2

3

the problem was that the OP tried to print the result before the threads were done. He should have waited for join.

import threading
import time

n = 0
array = [0]*10
sem = threading.Semaphore()

def proc(num):
  global n
  while True:
    sem.acquire()
    n = n+1
    sem.release()
    if n > 9:
        break
    array[n] = n
    print ("Thread {}: {}".format(num,array))
    time.sleep(0.25)

t1 = threading.Thread(target = proc, args=[1])
t2 = threading.Thread(target = proc, args=[2])
t1.start()
t2.start()
t1.join()
t2.join()
Sign up to request clarification or add additional context in comments.

2 Comments

This doesn't exactly do what OP is expecting. He should be printing the list in the thread worker function since he wants to show that the threads are synchronized at every index
rpg711 was right, I updated the answer to what I believe the OP intended.
1

Different take on a Semaphore pattern, handing the "tasks" within the Sempahore itself

class Sempahore:
    def __init__(self, max_threads):
        self.active_threads = 0
        self.max_threads = max_threads
        self.tasks = []

    def add_task(self, func, args):
        self.tasks.append(
            Task(
                func=func,
                args=args
            )
        )

    def run_task(self, task: Task):
        _func = task.func
        _args = task.args

        self.active_threads += 1
        _func(*_args)
        self.active_threads -= 1

    def run(self, blocking=False):
        if blocking:
            self._run()
        else:
            t = Thread(target=self._run)
            t.start()

    def _run(self):
        while True:
            if self.active_threads < self.max_threads:
                task = self.tasks.pop()
                logger.info(f'starting task: {task.task_id}')
                t = Thread(
                    target=self.run_task,
                    args=(task,))
                t.start()
            if len(self.tasks) == 0:
                break

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.