更多的主题混乱。为什么信号量太慢了?

时间:2015-04-16 05:59:50

标签: python multithreading performance semaphore

这个问题是我上一个问题(Threading in Python - What am I missing?)的续集。

感谢那些指出线程问题所在的人。这个问题终于解决了,我启用了信号量,并且很惊讶只是启用它们将程序的执行时间从几分之一秒缩短到4秒! WOW ......即使考虑到碰撞,仅仅80000次迭代的3秒似乎非常缓慢。

准确时间:

Without semaphore      0.0167980194092 s
With semaphore         2.76963996887 s

以下是代码:

import threading
import time
import random

turnstile_names = ["N", "E", "S", "W"]
count = 0
sem = threading.Semaphore(1)

class Incrementer(threading.Thread):
    def __init__(self, id):
        threading.Thread.__init__(self)
        self.id = id

    def run(self):
        global count, sem
        for i in range(20000):
            sem.acquire()
            count = count + 1
            sem.release()

def main():

    random.seed(507129)
    incrementers = [Incrementer(name) for name in turnstile_names]

    for incrementer in incrementers:
        incrementer.start()

    # We're running!

    for incrementer in incrementers:
        incrementer.join()

    print count
    return 0

if __name__ == '__main__':
    main()

2 个答案:

答案 0 :(得分:1)

我无法评论为什么信号量太慢,但有一种方法可以通过使用锁而不是信号量来显着加快代码速度:

lock = threading.Lock()

class Incrementer(threading.Thread):
    def __init__(self, id):
        threading.Thread.__init__(self)
        self.id = id

    def run(self):
        global count, lock
        for i in range(20000):
            with lock:
                count = count + 1

无同步:0.02s
信号量同步:2.69s
使用锁:0.36s

那就是说,我认为在略超过两秒半的时间内获取和发布信号量八万次是不错的性能 - 线程同步是有代价的 - 但你应该看看你的选项并选择适合的工具你的用例最好,在这种情况下它是一个锁,而不是一个信号量,因为你只有一个资源。

答案 1 :(得分:0)

信号量是在操作系统中实现的。它们提供了在其他进程之间进行同步的功能,而这是使用锁无法实现的。 因此,它们变慢的原因现在应该很明显,每次与信号量进行交互时,该过程都需要对OS进行系统调用,上下文切换到内核模式,执行逻辑,然后在遇到以下情况时再次将上下文切换回到调用过程它没有被阻止。