How do threads work in Python, and what are common Python-threading specific pitfalls?

前端 未结 7 1356
一个人的身影
一个人的身影 2020-11-27 11:13

I\'ve been trying to wrap my head around how threads work in Python, and it\'s hard to find good information on how they operate. I may just be missing a link or something,

相关标签:
7条回答
  • 2020-11-27 11:27

    Use threads in python if the individual workers are doing I/O bound operations. If you are trying to scale across multiple cores on a machine either find a good IPC framework for python or pick a different language.

    0 讨论(0)
  • 2020-11-27 11:37

    Try to remember that the GIL is set to poll around every so often in order to do show the appearance of multiple tasks. This setting can be fine tuned, but I offer the suggestion that there should be work that the threads are doing or lots of context switches are going to cause problems.

    I would go so far as to suggest multiple parents on processors and try to keep like jobs on the same core(s).

    0 讨论(0)
  • 2020-11-27 11:41

    Below is a basic threading sample. It will spawn 20 threads; each thread will output its thread number. Run it and observe the order in which they print.

    import threading
    class Foo (threading.Thread):
        def __init__(self,x):
            self.__x = x
            threading.Thread.__init__(self)
        def run (self):
              print str(self.__x)
    
    for x in xrange(20):
        Foo(x).start()
    

    As you have hinted at Python threads are implemented through time-slicing. This is how they get the "parallel" effect.

    In my example my Foo class extends thread, I then implement the run method, which is where the code that you would like to run in a thread goes. To start the thread you call start() on the thread object, which will automatically invoke the run method...

    Of course, this is just the very basics. You will eventually want to learn about semaphores, mutexes, and locks for thread synchronization and message passing.

    0 讨论(0)
  • 2020-11-27 11:41

    Note: wherever I mention thread i mean specifically threads in python until explicitly stated.

    Threads work a little differently in python if you are coming from C/C++ background. In python, Only one thread can be in running state at a given time.This means Threads in python cannot truly leverage the power of multiple processing cores since by design it's not possible for threads to run parallelly on multiple cores.

    As the memory management in python is not thread-safe each thread require an exclusive access to data structures in python interpreter.This exclusive access is acquired by a mechanism called GIL ( global interpretr lock ).

    Why does python use GIL?

    In order to prevent multiple threads from accessing interpreter state simultaneously and corrupting the interpreter state.

    The idea is whenever a thread is being executed (even if it's the main thread), a GIL is acquired and after some predefined interval of time the GIL is released by the current thread and reacquired by some other thread( if any).

    Why not simply remove GIL?

    It is not that its impossible to remove GIL, its just that in prcoess of doing so we end up putting mutiple locks inside interpreter in order to serialize access, which makes even a single threaded application less performant.

    so the cost of removing GIL is paid off by reduced performance of a single threaded application, which is never desired.

    So when does thread switching occurs in python?

    Thread switch occurs when GIL is released.So when is GIL Released? There are two scenarios to take into consideration.

    If a Thread is doing CPU Bound operations(Ex image processing).

    In Older versions of python , Thread switching used to occur after a fixed no of python instructions.It was by default set to 100.It turned out that its not a very good policy to decide when switching should occur since the time spent executing a single instruction can very wildly from millisecond to even a second.Therefore releasing GIL after every 100 instructions regardless of the time they take to execute is a poor policy.

    In new versions instead of using instruction count as a metric to switch thread , a configurable time interval is used. The default switch interval is 5 milliseconds.you can get the current switch interval using sys.getswitchinterval(). This can be altered using sys.setswitchinterval()

    If a Thread is doing some IO Bound Operations(Ex filesystem access or
    network IO)

    GIL is release whenever the thread is waiting for some for IO operation to get completed.

    Which thread to switch to next?

    The interpreter doesn’t have its own scheduler.which thread becomes scheduled at the end of the interval is the operating system’s decision. .

    0 讨论(0)
  • 2020-11-27 11:43

    Yes, because of the Global Interpreter Lock (GIL) there can only run one thread at a time. Here are some links with some insights about this:

    • http://www.artima.com/weblogs/viewpost.jsp?thread=214235
    • http://smoothspan.wordpress.com/2007/09/14/guido-is-right-to-leave-the-gil-in-python-not-for-multicore-but-for-utility-computing/

    From the last link an interesting quote:

    Let me explain what all that means. Threads run inside the same virtual machine, and hence run on the same physical machine. Processes can run on the same physical machine or in another physical machine. If you architect your application around threads, you’ve done nothing to access multiple machines. So, you can scale to as many cores are on the single machine (which will be quite a few over time), but to really reach web scales, you’ll need to solve the multiple machine problem anyway.

    If you want to use multi core, pyprocessing defines an process based API to do real parallelization. The PEP also includes some interesting benchmarks.

    0 讨论(0)
  • 2020-11-27 11:45

    Python's a fairly easy language to thread in, but there are caveats. The biggest thing you need to know about is the Global Interpreter Lock. This allows only one thread to access the interpreter. This means two things: 1) you rarely ever find yourself using a lock statement in python and 2) if you want to take advantage of multi-processor systems, you have to use separate processes. EDIT: I should also point out that you can put some of the code in C/C++ if you want to get around the GIL as well.

    Thus, you need to re-consider why you want to use threads. If you want to parallelize your app to take advantage of dual-core architecture, you need to consider breaking your app up into multiple processes.

    If you want to improve responsiveness, you should CONSIDER using threads. There are other alternatives though, namely microthreading. There are also some frameworks that you should look into:

    • stackless python
    • greenlets
    • gevent
    • monocle
    0 讨论(0)
提交回复
热议问题