directory

thread

Thread communication

Producers and consumers

Thread scheduling

Computation-intensive and IO intensive

coroutines


thread

To do more than one thing at a time within a process, you need to run multiple 'sub-tasks' at the same time. We call these sub-tasks threads. Threads are usually called lightweight threads. Threads are concurrent tasks that share memory space. The resource thread that each thread shares a process is the smallest execution unit, and the process must have at least one thread. How processes and threads are scheduled is entirely up to the operating system. The program cannot determine when and for how long they will be executedCopy the code

Example:

import threading
import time
def run() :
    print('Child thread %s starts' % (threading.current_thread().name))
    # Implement thread functionality
    print('print')
    time.sleep(1)

    print('Child thread %s ends' % (threading.current_thread().name))

if __name__=='__main__':
    By default, any process starts a thread, called the main thread. The main thread can start new child threads
    #current_thread() : Returns an instance of the current thread
    print('Main thread %s started' %(threading.current_thread().name))

    Create a child thread
    t = threading.Thread(target=run,name='runthread')
    t.start()
    Wait for the thread to end
    t.join()
    print('Main thread %s end' % (threading.current_thread().name))
Copy the code

Running results:

The biggest difference between multi-process and multi-thread is that in multi-process, each variable has a copy in each process, which does not affect each other. In multithreading, all variables are shared by all threads. So any variable can be modified by any thread. So the biggest danger between threads is that changing a variable at the same time can mess things up.Copy the code

Example:

import threading
import time
n = 100
def run() :
    global n
    n = n + 20
    print('run:',n)

def fun() :
    global n
    n = n /10
    print('fun:',n)

if __name__=='__main__':
    Create a child thread
    t = threading.Thread(target=run,name='runthread')
    t.start()
    t.join()
    k = threading.Thread(target=fun, name='funthread')
    k.start()
Copy the code

Running results:

Thread locks solve data clutter Two threads work at the same time, one making a deposit and the other making a withdrawalCopy the code

You can set a local variable to a thread, using a threadLocal object

Example:

import threading
import time

num = 0
Create a global threadLocal object
Each thread has its own storage space
ThreadLocal objects can be read and written by each thread, but do not affect each other
local = threading.local()
list = [num,num]
def run(x,n) :
    x = x + n
    x = x - n
def fun(n) :
    Each thread has a local.x, which is a thread local variable
    local.x = num
    for i in range(100000):
        run(local.x,n)
    print('%s--%d' %(threading.current_thread().name,local.x))


if __name__=='__main__':
    Create a child thread
    t = threading.Thread(target=fun,args=(6,))
    t2 = threading.Thread(target=fun, args=(9,))
    t.start()
    t2.start()
    t.join()
    t2.join()
    print('num = ',num)
Copy the code

Running results:

 

Thread communication

The thread blocks and fires events

Example: The run() method will not be executed if e.set() is not used to trigger the event

import threading,time
def fun() :
    # event object
    event = threading.Event()
    def run() :
        for i in range(5) :Block, waiting for the event to trigger
            event.wait()
            # reset
            event.clear()
            print('what happen ... %d' % i)
    t = threading.Thread(target=run).start()
    return event

e = fun()
# trigger event
for i in range(5):
    e.set()
    time.sleep(1)
Copy the code

Running results:

 

Producers and consumers

Four producers are producing data and three consumers are pulling production data out of the queue

import threading,time,queue,random

# producers
def product(id,q) :
    while True:
        num = random.randint(0.10000)
        q.put(num)
        print('Producer %d produces % D data to queue' % (id,num))
        time.sleep(3)
    # Mission completed
    q.task_done()

# consumers
def customer(id,q) :
    while True:
        item = q.get()
        if item is None:
            break
        print('Consumer %d consumes % D data' % (id,item))
        time.sleep(2)
    # Mission completed
    q.task_done()

if __name__=='__main__':
    # message queue
    q = queue.Queue()
    # Start producer 4
    for i in range(4):
        threading.Thread(target=product,args=(i,q)).start()
    # Start Consumer 3
    for i in range(3):
        threading.Thread(target=customer,args=(i,q)).start()
Copy the code

Running results:

 

Thread scheduling

Schedules the execution order between two threads

import threading,time

# thread condition variables
cond = threading.Condition()

def run1() :
    with cond:
        for i in range(0.10.2) :print(threading.current_thread().name,i)
            time.sleep(1)
            Run once and wait for run2 information
            cond.wait()
            cond.notify()

def run2() :
    with cond:
        for i in range(1.10.2) :print(threading.current_thread().name,i)
            time.sleep(1)
            Send a message to RUN1
            cond.notify()
            # wait
            cond.wait()

threading.Thread(target=run1).start()
threading.Thread(target=run2).start()
Copy the code

Running results:

 

Computation-intensive and IO intensive

Computation-intensive

It takes a lot of computing and consumes CPU resources, such as calculating PI, decoding video in high definition and so on, all depending on the CPU’s computing power. This type of computationally intensive task can also be accomplished with multi-task, but the more tasks, the more time spent switching between tasks, and the less efficient the CPU performs the task. Therefore, for the most efficient utilization of the CPU, the number of computationally intensive tasks concurrently should be equal to the number of CPU cores

IO intensive

Tasks involving network and disk I/O are IO intensive tasks. These tasks consume little CPU and spend most of the time waiting for I/O operations to complete (because the I/O speed is much lower than that of CPU and memory). For IO intensive tasks, the more tasks, the higher THE CPU efficiency, but there is a limit. Most common tasks are I0-intensive, such as Web applications

 

coroutines

A procedure/function: of all the voice is call hierarchy, such as A call to B, in the process of B to perform and can invoke the C, C complete return, return B has been completed, the final is A complete one thread is to perform A subroutine, subroutine call is always an entry, A return, call the order is clear

Overview of coroutines: It also looks like a subroutine, but during execution, it can break inside the subroutine and then switch to another subroutine. So not a function call, kind of like a CPU interrupt

Coroutines are extremely efficient compared to threads. Because there is only one thread, there are no multiple variables written at the same time, there are no variable conflicts, there is no lock on resource sharing in coroutine, only need to determine the state

Example: subroutine call

def C() :
    print('C---START')
    print('C---END')
def B() :
    print('B---START')
    C()
    print('B---END')
def A() :
    print('A---START')
    B()
    print('A---END')

A()
Copy the code

Running results:

Python support for coroutines is implemented through generatorsCopy the code

Example: coroutines

def A() :
    print(1)
    yield 10
    print(2)
    yield 20
    print(3)
    yield 30
The simplest style of the coroutine controls the phase execution of the function, saving thread or process switching
The return value is a generator
a = A()
print(type(a))
print(next(a))
print(next(a))
print(next(a))
Copy the code

Running results:

Example:

def A() :
    Data is always null
    data = ' '
    r = yield data
    print(1,r,data)
    r = yield data
    print(2,r,data)
    r = yield data
    print(3,r,data)
    r = yield data

a = A()
# start a
print(a.send(None))
print(a.send('a'))
Copy the code

Running results:

 

 

 

Learn together and make progress together. If there are any mistakes, please comment