Semaphores on Python

后端 未结 4 1080
无人共我
无人共我 2020-12-29 22:24

I\'ve started programming in Python a few weeks ago and was trying to use Semaphores to synchronize two simple threads, for learning purposes. Here is what I\'ve got:

<
相关标签:
4条回答
  • 2020-12-29 23:05

    It is working fine, its just that its printing too fast for you to see . Try putting a time.sleep() in both functions (a small amount) to sleep the thread for that much amount of time, to actually be able to see both 1 as well as 2.

    Example -

    import threading
    import time
    sem = threading.Semaphore()
    
    def fun1():
        while True:
            sem.acquire()
            print(1)
            sem.release()
            time.sleep(0.25)
    
    def fun2():
        while True:
            sem.acquire()
            print(2)
            sem.release()
            time.sleep(0.25)
    
    t = threading.Thread(target = fun1)
    t.start()
    t2 = threading.Thread(target = fun2)
    t2.start()
    
    0 讨论(0)
  • 2020-12-29 23:10

    Also, you can use Lock/mutex method as following:

    import threading
    import time
    
    mutex = threading.Lock()  # is equal to threading.Semaphore(1)
    
    def fun1():
        while True:
            mutex.acquire()
            print(1)
            mutex.release()
            time.sleep(.5)
    
    def fun2():
        while True:
            mutex.acquire()
            print(2)
            mutex.release()
            time.sleep(.5)
    
    t1 = threading.Thread(target=fun1).start()
    t2 = threading.Thread(target=fun2).start()
    

    Another/Simpler style usage through "with":

    import threading
    import time
    
    mutex = threading.Lock()  # is equal to threading.Semaphore(1)
    
    def fun1():
        while True:
            with mutex:
                print(1)
            time.sleep(.5)
    
    def fun2():
        while True:
            with mutex:
                print(2)
            time.sleep(.5)
    
    t1 = threading.Thread(target=fun1).start()
    t2 = threading.Thread(target=fun2).start()
    

    [NOTE]:

    The difference between mutex, semaphore, and lock

    0 讨论(0)
  • 2020-12-29 23:10

    I used this code to demonstrate how 1 thread can use a Semaphore and the other thread will wait (non-blocking) until the Sempahore is available.

    This was written using Python3.6; Not tested on any other version.

    This will only work is the synchronization is being done from the same thread, IPC from separate processes will fail using this mechanism.

    import threading
    from  time import sleep
    sem = threading.Semaphore()
    
    def fun1():
        print("fun1 starting")
        sem.acquire()
        for loop in range(1,5):
            print("Fun1 Working {}".format(loop))
            sleep(1)
        sem.release()
        print("fun1 finished")
    
    
    
    def fun2():
        print("fun2 starting")
        while not sem.acquire(blocking=False):
            print("Fun2 No Semaphore available")
            sleep(1)
        else:
            print("Got Semphore")
            for loop in range(1, 5):
                print("Fun2 Working {}".format(loop))
                sleep(1)
        sem.release()
    
    t1 = threading.Thread(target = fun1)
    t2 = threading.Thread(target = fun2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("All Threads done Exiting")
    

    When I run this - I get the following output.

    fun1 starting
    Fun1 Working 1
    fun2 starting
    Fun2 No Semaphore available
    Fun1 Working 2
    Fun2 No Semaphore available
    Fun1 Working 3
    Fun2 No Semaphore available
    Fun1 Working 4
    Fun2 No Semaphore available
    fun1 finished
    Got Semphore
    Fun2 Working 1
    Fun2 Working 2
    Fun2 Working 3
    Fun2 Working 4
    All Threads done Exiting
    
    0 讨论(0)
  • 2020-12-29 23:19

    In fact, I want to find asyncio.Semaphores, not threading.Semaphore, and I believe someone may want it too.

    So, I decided to share the asyncio.Semaphores, hope you don't mind.

    from asyncio import (
        Task,
        Semaphore,
    )
    import asyncio
    from typing import List
    
    
    async def shopping(sem: Semaphore):
        while True:
            async with sem:
                print(shopping.__name__)
            await asyncio.sleep(0.25)  # Transfer control to the loop, and it will assign another job (is idle) to run.
    
    
    async def coding(sem: Semaphore):
        while True:
            async with sem:
                print(coding.__name__)
            await asyncio.sleep(0.25)
    
    
    async def main():
        sem = Semaphore(value=1)
        list_task: List[Task] = [asyncio.create_task(_coroutine(sem)) for _coroutine in (shopping, coding)]
        """ 
        # Normally, we will wait until all the task has done, but that is impossible in your case.
        for task in list_task:
            await task
        """
        await asyncio.sleep(2)  # So, I let the main loop wait for 2 seconds, then close the program.
    
    
    asyncio.run(main())
    

    output

    shopping
    coding
    shopping
    coding
    shopping
    coding
    shopping
    coding
    shopping
    coding
    shopping
    coding
    shopping
    coding
    shopping
    coding
    

    16*0.25 = 2

    0 讨论(0)
提交回复
热议问题