python [threading] data stacking

threading

  • threading
    • thread local data
    • thread object
    • properties and methods
      • start()
      • run()
      • join()
      • is_alive()
      • identify
      • native_id
      • name
      • threading. active_count()
      • threading. current_thread()
    • lock
      • acquire(blocking=True, timeout=-1)
      • release()
      • locked()
  • 1.python main thread and sub-thread concurrency
  • 2.Python uses threading module as much as possible
  • 3. The difference between block sleep wait:
  • 4. Condition variable condition variable
  • 5. Thread-brief state model (informal)
  • 6. thread. Timer
  • 7. Data sharing between threads
    • 1.event event
    • 2. lock
    • 3.queue
  • 8. Shared variable types
  • 9. Return data from thread
  • 10.Semaphore

threading

Organize knowledge about threading

Thread local data

Thread-local data is thread-specific data. To manage thread-local data, just create an instance of local (or a subtype) and store properties in the instance:

mydata = threading. local()
mydata.x = 1

thread object

The Thread class represents activities that run in separate threads of control. There are two ways to specify an activity: passing a callable object to the constructor or overriding the run() method in a subclass. Other methods should not be overridden in subclasses (except constructors). In other words, only the init() and run() methods of this class can be overridden.

Once a thread object is created, its activity must be started by calling the thread’s start() method. This initiates the call to the run() method in a separate thread of control.

A thread is considered ‘alive’ once thread activity has begun. When its run() method terminates (whether normally or by throwing an unhandled exception), it is not ‘live’. The is_alive() method is used to check if the thread is alive.

Other threads can call a thread’s join() method. This blocks the thread that called this method until the thread on which the join() method was called terminates.

Threads have names. The name can be passed to the constructor, and can also be read or modified through the name attribute.

If the run() method raises an exception, threading.excepthook() is called to handle it. By default, threading.excepthook() silently ignores SystemExit.

A thread can be marked as a “daemon thread”. The meaning of this flag is that when the remaining threads are daemon threads, the entire Python program will exit. The initial value is inherited from the creating thread. This flag can be set via the daemon feature attribute or the daemon constructor parameter.

Properties and methods

start()

start()
Start thread activity.

It can only be called once in a thread. It arranges for the object’s run() method to be called in a separate thread of control.

If this method is called more than once in the same thread object, a RuntimeError will be thrown.

run()

A method representing thread activity.

You can override this method in subtypes. The standard run() method invokes the callable object (if any) passed as the target argument to this object constructor, with positional and keyword arguments taken from the args and kwargs arguments respectively.

join()

Wait until the thread terminates. This blocks the thread that called this method until the thread on which join() was called terminates – either normally or by throwing an unhandled exception – or until a timeout occurs, the timeout option is optional.

When the timeout parameter is present and not None, it should be a float or fraction specifying the timeout for the operation in seconds. Because join() always returns None , you must call is_alive() after join() to see if a timeout has occurred – if the thread is still alive, join() times out.

When the timeout parameter does not exist or is None , the operation will block until the thread terminates.

join() raises a RuntimeError exception if attempting to join the current thread would result in a deadlock. The same exception is also thrown if attempting to join() a thread that has not yet started.

is_alive()

is_alive()
Returns whether the thread is alive.

This method returns True when the run() method has just started until the run() method has just ended. The module function enumerate() returns a list containing all live threads.

ident

After the thread is started, the python interpreter assigns the thread the logo

# example of reporting the thread identifier
from threading import Thread
# create the thread
thread = Thread()
# report the thread identifier
print(thread.ident)
# start the thread
thread. start()
# report the thread identifier
print(thread.ident)
-----------------------------
output
none
164284

native_id

This is allocated by the underlying os

# example of reporting the thread identifier
from threading import Thread
# create the thread
thread = Thread()
# report the thread identifier
print(thread.ident)
print(thread. native_id)
# start the thread
thread. start()
# report the thread identifier
print(thread.ident)
print(thread. native_id)
--------------
output:
none
none
234468
234468

It shows that python starts the thread on the real operating system level

name

# example of setting the thread name via the property
from threading import Thread
# create a thread
thread = Thread()
# set the name
thread.name = 'MyThread'
# report thread name
print(thread.name)

threading. active_count()

indicates the number threads that are “alive”

# report the number of active threads
from threading import active_count
# get the number of active threads
count = active_count()
# report the number of active threads
print(count)

threading. current_thread()

# retrieve the current thread within
from threading import Thread
from threading import current_thread
 
# function to get the current thread
def task():
    # get the current thread
    thread = current_thread()
    # report the name
    print(thread.name)
 
# create a thread

thread = Thread(target=task)
print(current_thread().name)
# start the thread
thread. start()
# wait for the thread to exit
thread. join()
print(current_thread().name)
output:
MainThread
Thread-11
MainThread

##some example

You can see that it is in the initial attitude
before .start()


Stopped after running

lock

A primitive lock is a synchronization primitive component that does not belong to a specific thread at the time of locking. In Python, it is the lowest-level synchronization primitive available, implemented directly by the _thread extension module.

A raw lock is in one of two states, “locked” or “unlocked”. It is unlocked when it is created. It has two basic methods, acquire() and release() . When the state is unlocked, acquire() changes the state to locked and returns immediately. When the state is locked, acquire() will block until another thread calls release() to change it to the unlocked state, and then the acquire() call resets it to the locked state and returns. release() is only called on a locked state; it changes the state to unlocked and returns immediately. If an attempt is made to release a non-locked lock, a RuntimeError exception will be raised.

Locks also support the context management protocol.

When multiple threads are blocked in the acquire() waiting state to change to unlocked, and then release() resets the state to unlocked, only one thread can continue to execute; as to which waiting thread continues to execute is not defined, and will depend on the implementation different.

All method executions are atomic.

acquire(blocking=True, timeout=- 1)

Locks can be acquired blocking or non-blocking.

When called with the argument blocking set to True (the default), block until the lock is released, then lock the lock and return True .

Called with the parameter blocking set to False, no blocking will occur. Blocks if called with blocking set to True and returns False immediately; otherwise, locks the lock and returns True.

When the parameter timeout is called with a floating point number set to a positive value, block for at most the number of seconds specified by timeout, during which time the lock cannot be acquired. Setting the timeout parameter to -1 specifies an unbounded wait. It is forbidden to specify a timeout when blocking is False .

Returns True if the lock was acquired successfully, False otherwise (for example when a timeout occurs).

Changed in version 3.2: New timeout parameter.

Changed in version 3.2: Lock acquisition can now be interrupted by signals on POSIX if the underlying thread implementation supports it.

release()

Release a lock. This method can be called from any thread, not just the thread that acquired the lock.

When the lock is locked, reset it to unlocked, and return. If other threads are blocked waiting for this lock to be unlocked, only one of them is allowed.

A RuntimeError is raised when the call is made on an unlocked lock.

There is no return value.

locked()

Return True when the lock is acquired.

based program language: python

thread thread

1.python main thread and sub-thread concurrency

The form of switching is as follows

import time
import threading

def thread_1(i):
    time. sleep(2)
    print("Active current thread right now:", (threading. current_thread()))
    print('Value by Thread 1:', i)

def thread_2(i):
    time. sleep(5)
    print("Active current thread right now:", (threading. current_thread()))
    print('Value by Thread 2:', i)
    
def thread_3(i):
    print("Active current thread right now:", (threading. current_thread()))
    print("Value by Thread 3:", i)
    
# Creating sample threads
thread1 = threading.Thread(target=thread_1, args=(1,))
thread2 = threading.Thread(target=thread_2, args=(2,))
thread3 = threading.Thread(target=thread_3, args=(3,))

print("Active current thread right now:", (threading. current_thread()))
#3 Initially it is the main thread that is active

# Starting the threads
thread1. start()
thread2. start()
thread3. start()
-------------------------------------------------- ------------------
output:

Active current thread right now: <_MainThread(MainThread, started 140048551704320)>
Active current thread right now: <Thread(Thread-3, started 140048508823296)>
Value by Thread 3: 3
Active current thread right now: <Thread(Thread-1, started 140048525608704)>
Value by Thread 1: 1
Active current thread right now: <Thread(Thread-2, started 140048517216000)>
Value by Thread 2: 2

2.python try to use threading module

t = threading.Thread(target=?,name=?,args=?) -> initialize
There are the following methods:

t.start()
t. run()
t. current_thread()
t. isDaemon()
t. setName(?)
t. SetDaemon(True)
t. join()
t.is_alive()

Combining the state model of thread; initialize ready running blocked terminated understanding

3. The difference between block sleep wait:

In fact, there is no need to deliberately distinguish between the two, because both will suspend the execution of the thread.

  • The difference between the two is:

    • Entering the waiting state is active for the thread, while entering the blocked state is passive.
    • Furthermore, entering the blocking state is synchronous, while entering the wait state is within synchronous code.
    • The thread that calls the sleep method is directly scheduled by the CPU, while wait waits for another java thread to call notify in the synchronization block holding the same object lock.
  • What both have in common is:

    • Both temporarily stop the execution of the thread, and the thread itself does not occupy a CPU time slice.

4. Condition variable condition variable

threading.Condition to notify a waiting thread that something has happened.

import threading
# Can pass in a mutex or reentrant lock
cond = threading. Condition()
# example of wait/notify with a condition
from time import sleep
from threading import Thread
from threading import Condition
 
# target function to prepare some work
def task(condition, work_list):
    # block for a moment
    sleep(1)
    # add data to the work list
    work_list.append(33)
    # notify a waiting thread that the work is done
    print('Thread sending notification...')
    with condition:
        condition. notify()
 
# create a condition
condition = Condition()
# prepare the work list
work_list = []
# wait to be notified that the data is ready
print('Main thread waiting for data...')
with condition:
    # start a new thread to perform some work
    worker = Thread(target=task, args=(condition, work_list))
    worker. start()
    # wait to be notified
    condition. wait()
# we know the data is ready
print(f'Got data: {<!-- -->work_list}')

5. Thread brief state model (informal)

6. thread. Timer

The function is to execute after the timer

#SuperFastPython.com
# example of using a thread timer object
from time import sleep
from threading import Timer
 
# target task function
def task(message):
    # report the custom message
    print(message)
 
# create a thread timer object
timer = Timer(3, task, args=('Hello world',))
# start the timer object
timer. start()
# block for a moment
sleep(1)
# cancel the thread
print('Canceling the timer...')
timer. cancel()

7. Data sharing between threads

Three common approaches include:

  • Sharing a boolean variable with a threading.Event. Passed event
  • Protecting shared data with a threading.Lock. Through the lock
  • Sharing data with a queue.Queue. Through the queue

1.event event

1. The event class will protect a boolean variable ensuring all access and change to the variable is thread safe, avoiding race conditions

# set the event true
event. set()
#...
# set the event false
event. clear()
# example of using an event object
from time import sleep
from random import random
from threading import Thread
from threading import Event
 
# target task function
def task(event, number):
    # wait for the event to be set
    event. wait()
    # begin processing
    value = random()
    sleep(value)
    print(f'Thread {<!-- -->number} got {<!-- -->value}')
 
# create a shared event object
event = Event()
# create a suite of threads
for i in range(5):
    thread = Thread(target=task, args=(event, i))
    thread. start()
# block for a moment
print('Main thread blocking...')
sleep(2)
# start processing in all threads
event. set()
# wait for all the threads to finish... ?

2.lock

# acquire the lock
lock. acquire()
try:
    # critical section...
finally:
    # always release the lock
    lock. release()
...
# create a shared lock
lock = threading.Lock()
...
# acquire the lock
with lock:
# read or write the shared variable
...

3.queue

The queue module provides a number of queue types, such as:

  • Queue: A fully-featured first-in-first-out (FIFO) queue.
  • SimpleQueue: A FIFO queue with less functionality.
  • LifoQueue: A last-in-first-out (LIFO) queue.
  • PriorityQueue: A queue where the first items out are those with the highest priority.
# loop forever
while True:
# get an item of data from the queue
data = queue. get()
#...

8. Shared variable types

  • Local variables within a function.
  • Global variables defined in a script.
  • Instance variables defined in a class.

9. Return data from thread

The thread can own __init__ attribute, and then read it.
class MyThread(threading.Thread)
def __init__(self):
#define an instance variable
self.data = 33
# define a lock to protect the instance variable
self. lock = threading. Lock()
\t
# method on the class
def task(self):
# acquire the lock
with self. lock:
# modify the instance variable
self.data = 22

10.Semaphore

A semaphore is essentially a counter protected by a mutex lock, used to limit the number of threads that can access a resource.

# example of using a semaphore
from time import sleep
from random import random
from threading import Thread
from threading import Semaphore
 
# target function
def task(semaphore, number):
    # attempt to acquire the semaphore
    with semaphore:
        # process
        value = random()
        sleep(value)
        # report result
        print(f'Thread {<!-- -->number} got {<!-- -->value}')
 
# create a semaphore
semaphore = Semaphore(2) #limit the number of concurrent processing threads to 2.
# create a suite of threads
for i in range(10):
    worker = Thread(target=task, args=(semaphore, i))
    worker. start()
# wait for all workers to complete...