Python Threading in detail

  • 2020-06-19 10:56:12
  • OfStack

Python's threading module is loosely based on Java's threading module. But now threads have no priority, no thread group, and cannot be destroyed, stopped, paused, started, and interrupted. Static methods of the Java Thread class, migrated to module methods.

main thread: The thread that runs the python program

daemon thread daemon thread, if all threads outside the daemon thread have ended. The daemon thread also terminates and forces the entire program to terminate. Do not do resource related operations in the daemon. Causes the resource not to be released correctly. Use Event for non-daemons.

Thread class


(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

group:  For the following ThreadGroup Class reserved 
target:  The object to be executed by run() Methods to perform 
args: target The parameters used by the 
daemon:  Is a daemon 

start()

Each thread object can only be called once start()

run()

Override this method if you create a subclass of Thread. Responsible for executing executable objects passed by the target parameter.

join()

Block the thread until it is finished.

GIL

In CPython, Python can execute only one thread at a time because of GIL. To take full advantage of the computing resources of multi-core machines, use multiprocessing or concurrent.futures.ProcessPollExecutor. However, if you want a lot of I/ ES55en-related concurrency, threding is still a good choice. ? Because the system automatically realizes the thread context switch.


from threading import Thread
import requests
url = 'http://www.baidu.com'
urls = [url]*20
threads = []

for url in urls:
  t = Thread(target=requests.get, args=(url, ))
  t.start()
  threads.append(t)
for t in threads:
  t.join()

The lock (Lock) objects

The original lock (primitive lock), when locked, is a synchronization primitive that does not belong to any one thread (synchronization primitive). In Python, it is the lowest level synchronization primitive currently available, provided by the _thread module.

A primitive lock has two states: locked and unlocked. When the lock is created, it is in the unlocked state. Locks are made up of two basic methods: acquire() and release().

When in the unlocked state, the acquire(() method can change the state to locked and return immediately. When in the locked state, acquire() blocks until another thread calls release() to unlock the change lock, then acquire() locks the lock and returns.

The release() method can only be called when locked is locked and the lock is released. Otherwise, an RuntimeError error is thrown.

If there are multiple acquire() waiting to be unlocked, it is not clear which one will be triggered.

class threading.Lock

If a thread acquire locks a lock, subsequent threads that acquire it will block until the lock is released. Any thread can release the lock.

Lock is a factory function that returns an instance of the most efficient concrete Lock class in the current platform.

Lock supports the context management method (context management protocol), which is the with statement. Locks are used in the presence of race conditions (race condition). Multiple threads, for example, work together on a piece of data.


#  from python Cookbook
import threading
class SharedCounter:
  def __init__(self, init_value=0):
    self._value = init_value
    self._value_lock = threading.Lock()  
  def incr(self, delta=1):
    #  It's used here with  Statement, create 1 Lock, added value, release lock. 
    with self._value_lock:
      self._value += 1

RLock object

Reentrant locking (reentrant lock). It feels like a lock in a lock, which is a recursive lock. Wait until you see a concrete example of how to use it.

Condition object

The condition variable is always associated with a lock, which can be passed in or created by default. Passing a lock is useful if there are multiple condition objects that need to share a lock. The lock is part 1 of the condition object, and you don't have to track it.

Timer object

Timer is a subclass of Thread, so it also accepts the function parameter, which can also be start(). Its run() function is rewritten to start event.wait (interval) before starting function.

Barrier object

Achieve a common advance and retreat for certain services.


threading.Barrier(parties, action=None, timeout=None)

Set n=parties threads. When n barrier.wait () is called, all the calls are blocked and action is executed

It feels like the Barrier can do a lot of complicated things.


Related articles: