SoFunction
Updated on 2024-11-12

Python Threading Usage Details

Python's threading module is loosely based on Java's threading module. But now threads have no priority, no thread groups, and cannot be destroyed, stopped, paused, started, or interrupted. The static methods of the Java Thread class are ported to module methods.

main thread: the thread that runs the python program

The daemon thread daemon thread, if all threads outside the daemon thread are terminated. The daemon thread will also end and force the termination of the entire program. Do not perform resource-related operations in the daemon thread. It will result in resources not being released correctly. Use Event in non-daemon processes.

Thread class

(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
group: To prepare for futureThreadGroupclass set-aside
target: executed object,leave it (to sb)run()method execution
args: targetParameters used by the object
daemon: Whether or not it is a daemon

start()

Each thread object can only be called start() once.

run()

Overrides this method if a subclass of Thread is created. Responsible for executing the executable object passed in the target argument.

join()

Block the thread until it ends.

GIL

In CPython, Python can only execute one thread at a time due to GIL. To fully utilize the computational resources of a multi-core machine you need to use either multiprocessing or. But, but if you want a lot of I/O-related concurrent operations, threding is still a good choice . Because the system automatically implements thread context switching.

from threading import Thread
import requests
url = ''
urls = [url]*20
threads = []

for url in urls:
  t = Thread(target=, args=(url, ))
  ()
  (t)
for t in threads:
  ()

lock object (computing)

A primitive lock, when it locks, is a synchronization primitive that doesn't belong to any one thread. 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; a lock is created in the unlocked state. A lock consists of two basic methods: acquire() and release().

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

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

If there is more than one acquire() waiting to be unlocked, there is no certainty as to which which will be triggered.

class

If a thread acquires a lock, subsequent threads that acquire it are blocked until the lock is released. Any thread can release a lock.

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

Lock supports the context management protocol, which is the with statement. Locks are used when there is a race condition. For example, when multiple threads are working together on a piece of data.

# From the python Cookbook
import threading
class SharedCounter:
  def __init__(self, init_value=0):
    self._value = init_value
    self._value_lock = ()  
  def incr(self, delta=1):
    # The with statement is used here to create a lock, increase the value, and release the lock.
    with self._value_lock:
      self._value += 1

RLock object

A reentrant lock. It feels like a lock within a lock, that is, a recursive lock. I'll write more about it when I see a concrete example of its application.

Condition object

The condition variable is always associated with a lock of some kind, which can either 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 of the condition object, you don't have to keep track of it intentionally.

Timer object

Timer is a subclass of Thread, so it also has to accept the function parameter and can also be started(). Its run() function is rewritten to first (interval) and then start function.

Barrier objects

Achieving co-mingling of certain services.

(parties, action=None, timeout=None)

Set up n=parties threads so that when n ()'s are called, the blocking of all those calls is lifted at the same time and the action is executed

It feels like Barrier allows for a lot of complexity.