Fully parsing different python threads

thread

The scheduling unit of CPU is simply the end executor in the program, which is equivalent to the position of younger brother.

Some people say that the thread in python is a chicken rib because of GIL, but it is not a chicken rib. After all, it works well when performing io operations, but it is unsatisfactory when performing calculations.

Let's see how to use threads:

1. Import thread module:

import threading as t

2. Thread usage

tt=t.Thread(group=None,target=None,name=None,args=(),kwargs={},name='',daemon=None)
group:Thread group, must be None
target:Running functions
args:Parameter tuple of the incoming function
kwargs:Parameter Dictionary of the incoming function
name:Thread name
daemon:Whether the thread exits with the main thread(Daemons)
​
Thread The return value of the method also has the following methods:
tt.start() : Activate thread,
tt.getName() : Get the name of the thread
tt.setName() : Set the name of the thread
tt.name : Gets or sets the name of the thread
tt.is_alive() : Judge whether the thread is active
tt.isAlive() : Judge whether the thread is active
tt.setDaemon() Set as daemons (default: False)
tt.isDaemon() : Determine whether it is a guardian thread
tt.ident : Gets the identifier of the thread. Only when called start()Method before the property is valid
tt.join() : Execute each thread one by one, and continue to execute after execution
tt.run() : Auto execute thread object
​
t The methods are as follows:
t.active_count(): Returns the number of running threads
t.enumerate(): Returns the list of running threads
t.current_thread().getName() Get the name of the current thread
t.TIMEOUT_MAX set up t Global timeout for

Let's take a look at this:

3. Create thread

Threads can be created by Thread method, or can override the run method implementation of Thread class. Threads can be divided into single Thread and multi Thread.

Using the Thread method to create

1. Single thread

def xc():
    for y in range(100):
        print('In operation'+str(y))
tt=t.Thread(target=xc,args=()) #Method join to thread
tt.start()  #Start thread
tt.join() #Wait for child thread to end

2. Multithreading

def xc(num):
    print('function:'+str(num))
c=[]
for y in range(100):
    tt=t.Thread(target=xc,args=(y,))
    tt.start() #Start thread
    c.append(tt) #Create list and add thread
for x in c:
    x.join()  #Wait for child thread to end

Class method of rewriting thread

1. Single thread

class Xc(t.Thread): #Inherit Thread class
    def __init__(self):
        super(Xc, self).__init__()
    def run(self):  #Override run method
        for y in range(100):
            print('In operation'+str(y))
x=Xc()
x.start() #Start thread
x.join()  #Wait for child thread to end
​
//It can also be written as follows:
Xc().run() The effect is the same as above

2. Multithreading

class Xc(t.Thread): #Inherit Thread class
    def __init__(self):
        super(Xc, self).__init__()
    def run(self,num):  #Override run method
        print('function:'+str(num))
x=Xc()
for y in range(10):
    x.run(y) #function

Line lock

Why do you need to lock it? Look at this and you will know:

When multithreading accesses an object at the same time, it will occupy resources, so we have to tie it down, so we need to add a Lock to Lock it, which is a synchronous Lock. To unlock, we must first create a Lock. There are two types of locks in the thread: Lock and RLock.

1,Lock

usage method:

#Acquire lock
 When the lock cannot be acquired, it will enter the blocking state by default and set the timeout until the lock is acquired. Timeout disable setting when non blocking. If the timeout still fails to acquire the lock, return False.
Lock.acquire(blocking=True,timeout=1)
​
#Release the lock. The locked lock will be set to unlocked. If the call is unlocked, a RuntimeError exception is thrown.
Lock.release()

Mutually exclusive lock, synchronous data, solve the security problem of multithreading:

n=10
lock=t.Lock()
def xc(num):
    lock.acquire()
    print('function+: '+str(num+n))
    print('function-: '+str(num-n))
    lock.release()
c=[]
for y in range(10):
    tt=t.Thread(target=xc,args=(y,))
    tt.start()
    c.append(tt)
for x in c:
    x.join()

In this way, it seems to be organized, and the output is first + then -. Lock using the same resource multiple times in a thread can cause a deadlock.

Deadlock problem:

n=10
lock1=t.Lock()
lock2=t.Lock()
def xc(num):
  lock1.acquire()
  print('function+: '+str(num+n))
  lock2.acquire()
  print('function-: '+str(num-n))
  lock2.release()
  lock1.release()
c=[]
for y in range(10):
  tt=t.Thread(target=xc,args=(y,))
  tt.start()
  c.append(tt)
for x in c:
  x.join()

2,RLock

Compared with Lock, it can be recursive, supports multiple requests for the same resource in the same thread, and allows multiple locks in the same thread, but acquire and release must appear in pairs.

Use recursive locks to resolve deadlocks:

n=10
lock1=t.RLock()
lock2=t.RLock()
def xc(num):
  lock1.acquire()
  print('function+: '+str(num+n))
  lock2.acquire()
  print('function-: '+str(num-n))
  lock2.release()
  lock1.release()
c=[]
for y in range(10):
  tt=t.Thread(target=xc,args=(y,))
  tt.start()
  c.append(tt)
for x in c:
  x.join()

At this time, the output variable becomes just one, and does not grab resources at will. For thread locks, with can also be used more easily:

#with context management, lock object supports context management
with lock:   #with means to open the automatic release lock automatically
  for i in range(10): #No one else can work during lock up
    print(i)
  #The top and the bottom are equivalent
if lock.acquire(1):#Lock success and continue to work. Wait until you lock success. 1 means exclusive
  for i in range(10): #Other threads cannot work during lock
    print(i)
  lock.release() #Release lock

3. Conditional lock

Wait to pass. Condition(lock=None) can be passed in lock or Rlock. The default Rlock is used as follows:

Condition.acquire(*args) acquire lock
 Condition.wait(timeout=None) wait for notification, timeout set timeout
 Condition.notify(num) wakes up at most a specified number of waiting threads, without which there is no operation
 Condition.notify_all() wakes up all waiting threads or notifyAll()

def ww(c):
  with c:
    print('init')
    c.wait(timeout=5) #Set wait timeout 5
    print('end')
def xx(c):
  with c:
    print('nono')
    c.notifyAll() #Wake all threads
    print('start')
    c.notify(1) #Wake up a thread
    print('21')
c=t.Condition() #Create conditions
t.Thread(target=ww,args=(c,)).start()
t.Thread(target=xx,args=(c,)).start()

In this way, you can wake up other threads existing in other functions in the wake-up function while waiting.

Semaphore

Semaphores can be divided into bounded semaphores and unsolved semaphores. Let's see their usage specifically:

1. Bounded semaphore

It does not allow release to be used outside the range of the initial value, otherwise, a ValueError exception is thrown.

#Construction method. value is the initial semaphore. value is less than 0, throw ValueError exception
b=t.BoundedSemaphore(value=1)
​
#When the semaphore is acquired, the counter is decremented by 1, i.e_ The value of value is reduced by 1. If_ A value of 0 becomes blocked. Get success return True
BoundedSemaphore.acquire(blocking=True,timeout=None)
​
#Release semaphore, counter plus 1. I.e_ Add 1 to the value of value. If the value exceeds the initialization value, an exception ValueError will be thrown.
BoundedSemaphore.release()
​
#Semaphore, current semaphore
BoundedSemaphore._value

You can see that there are multiple release s and an error is reported.

2. Unbounded semaphore

It does not check the upper limit of the release, but simply adds and subtracts the counter.

It can be seen that although there are more release s, there is no problem, and the number of semaphores is unlimited.

Event

For inter thread communication, the operation is performed by False or True of the flag set by the thread. The common methods are as follows:

event.set () flag set to True
 event.clear () flag set to False
 event.is_ Whether set() flag is True, if event.isSet()==False will block the thread;
Set the waiting time when flag is True and None is infinite. Wait until return to True, and return to False before timeout
event.wait(timeout=None)

Here is an example:

import time
e=t.Event()
def ff(num):
  while True:
    if num<5:
      e.clear()   #Clear signal sign
      print('empty')
    if num>=5:
      e.wait(timeout=1) #Wait signal is true
      e.set()
      print('start-up')
      if e.isSet(): #Clear flag if signal flag is true
        e.clear()
        print('stop it')
    if num==10:
      e.wait(timeout=3)
      e.clear()
      print('sign out')
      break
    num+=1
    time.sleep(2)
ff(1)

After setting the delay, you can see that the effect is quite obvious. We can do whatever we want him to do.

local

Each thread can be created to belong to its own variables (thread local variables), and their values are in the form of dictionaries in the thread that currently calls it.

Let's look at:

l=t.local()  #Create a thread local variable
def ff(num):
  l.x=100  #Set the value of the x method of the l variable to 100
  for y in range(num):
    l.x+=3 #change a value
  print(str(l.x))
​
for y in range(10):
  t.Thread(target=ff,args=(y,)).start() #Start execution thread

So, can the x method of a variable be set as a global variable? Let's look at:

It can be seen that he reported an error. The reason for the error is that there is no attribute x in this class. We can simply understand that local variables only accept local variables.

Timer

Set a timing plan to execute a method repeatedly within a specified time. His method of use is:

t.Timer(num,func,*args,**kwargs) #Restart the program again within the specified time

Let's look at:

def f():
  print('start')
  global t #Prevent thread piling up and final program exit
  tt= t.Timer(3, f)
  tt.start()
f()

In this way, the f function is executed every three seconds.

Through a comprehensive analysis of threads, we have learned the importance of threads, which can simplify our complex problems. It's quite useful for those who like to play reptiles. This article basically covers all the concepts of threads, hoping to help you.

Source network, for learning purposes only, invasion and deletion.

Don't panic. I have a set of learning materials, including 40 + E-books, 800 + teaching videos, involving Python foundation, reptile, framework, data analysis, machine learning, etc. I'm not afraid you won't learn! https://shimo.im/docs/JWCghr8prjCVCxxK/ Python learning materials

Pay attention to the official account [Python circle].

file

Keywords: Python less Attribute network

Added by greenhorn666 on Wed, 20 May 2020 10:16:40 +0300