SoFunction
Updated on 2024-11-16

A brief description of processes, threads, and co-programs in Python

The relationship and differences between processes, threads, and concurrencies have been bugging me for a while as well, and I've recently had some insights to write about.

Processes have their own independent heap and stack, neither share the heap nor the stack, and processes are scheduled by the operating system.

Threads have their own separate stack and shared heap, shared heap, not shared stack, and threads are also scheduled by the operating system (standard threads yes).

Concurrent threads share the heap, not the stack, as do threads, and concurrent threads are scheduled by the programmer shown in the code of the concurrent thread.

The difference between the process and the other two is still clear.

The difference between a concatenation and a thread is that a concatenation avoids pointless scheduling, and thus improves performance, but also, as a result, the programmer has to take responsibility for scheduling on his own, and concatenations lose the ability to use multiple CPUs with standard threads.

Python threads

Definition : Threading is used to provide thread-related operations; a thread is the smallest unit of work in an application.

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import time
def show(arg):
(1)
print 'thread'+str(arg)
for i in range(10):
t = (target=show, args=(i,))
()
print 'main thread stop 

The above code creates 10 "foreground" threads, and then the controller hands them over to the CPU, which schedules them according to a specified algorithm and executes the instructions in pieces.

More ways:

-Start thread is ready for CPU scheduling.

-setName Sets the name for the thread

-getName Get thread name

-setDaemon Set to background thread or foreground thread (default)

If it is a background thread, during the execution of the main thread, the background thread is also in progress, and after the main thread finishes executing, the background thread stops regardless of whether it succeeds or not

If it is a foreground thread, during the execution of the main thread, the foreground thread is also in progress, and after the main thread finishes executing, the program stops after waiting for the foreground thread to finish executing as well

-join executes each thread one at a time, and then continues on to the next, which makes multithreading meaningless.

-run Automatically executes the thread object's run method when the thread is dispatched by the cpu.

thread lock

Since threads are randomly scheduled with each other, and each thread may execute only n executions, the CPU then executes other threads. Therefore, the following problems may occur.

import threading
import time
gl_num = 0
def show(arg):
global gl_num
(1)
gl_num +=1
print gl_num
for i in range(10):
t = (target=show, args=(i,))
()

print 'main thread stop' 

import threading
import time
gl_num = 0
lock = ()
def Func():
()
global gl_num
gl_num +=1
(1)
print gl_num
()
for i in range(10):
t = (target=Func)
() 

event

Python thread events are used by the main thread to control the execution of other threads. events provide three main methods set, wait, and clear.

Mechanism of event handling: A "Flag" is defined globally, if the value of "Flag" is False, then the program will block when executing the method, if the value of "Flag "value is True, then the method will not block.

-clear: Set the "Flag" to False.

-set: Set the "Flag" to True.

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
def do(event):
print 'start'
()
print 'execute'
event_obj = ()
for i in range(10):
t = (target=do, args=(event_obj,))
()
event_obj.clear()
inp = raw_input('input:')
if inp == 'true':
event_obj.set() 

Python process

from multiprocessing import Process
import threading
import time
def foo(i):
print 'say hi',i
for i in range(10):
p = Process(target=foo,args=(i,))
() 

Note: Since each process needs to hold a copy of the data between them, there is a very large overhead required to create processes.

Process data sharing

Processes each hold a copy of the data and cannot share data by default

#!/usr/bin/env python
#coding:utf-8
from multiprocessing import Process
from multiprocessing import Manager
import time
li = []
def foo(i):
(i)
print 'say hi',li
for i in range(10):
p = Process(target=foo,args=(i,))
()
print ('ending',li) 

# Method I, Array

from multiprocessing import Process,Array
temp = Array('i', [11,22,33,44])
def Foo(i):
temp[i] = 100+i
for item in temp:
print i,'----->',item
for i in range(2):
p = Process(target=Foo,args=(i,))
()

#Method II: () Sharing data

from multiprocessing import Process,Manager
manage = Manager()
dic = ()
def Foo(i):
dic[i] = 100+i
print ()
for i in range(2):
p = Process(target=Foo,args=(i,))
()
() 
'c': ctypes.c_char, 'u': ctypes.c_wchar,
'b': ctypes.c_byte, 'B': ctypes.c_ubyte,
'h': ctypes.c_short, 'H': ctypes.c_ushort,
'i': ctypes.c_int, 'I': ctypes.c_uint,
'l': ctypes.c_long, 'L': ctypes.c_ulong,
'f': ctypes.c_float, 'd': ctypes.c_double 

When the process is created (not in use), the shared data is taken to the child process, and then assigned to the original value when execution in the process is complete.

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from multiprocessing import Process, Array, RLock
def Foo(lock,temp,i):
"""
Add 100 to the 0th digit
"""
()
temp[0] = 100+i
for item in temp:
print i,'----->',item
()
lock = RLock()
temp = Array('i', [11, 22, 33, 44])
for i in range(20):
p = Process(target=Foo,args=(lock,temp,i,))
() 

process pool

The process pool maintains a sequence of processes, and when used, a process is fetched from the pool. If there is no process in the pool sequence that can be used, the program waits until a process is available in the pool.

There are two methods in the process pool:

•apply

•apply_async

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from multiprocessing import Process,Pool
import time
def Foo(i):
(2)
return i+100
def Bar(arg):
print arg
pool = Pool(5)
#print (Foo,(1,))
#print pool.apply_async(func =Foo, args=(1,)).get()
for i in range(10):
pool.apply_async(func=Foo, args=(i,),callback=Bar)
print 'end'
()

()# Close processes in the process pool after they have finished executing, if commented out then the program closes directly

concurrent program

Threads and processes operate by programs triggering the system interface, and the final executioner is the system; co-programs operate by programmers.

The significance of the existence of concatenation: For multi-threaded applications, the CPU switches the execution between threads by slicing, and the thread switching is time consuming (save the state and continue next time). Concurrent threads, on the other hand, use only one thread to specify the order of execution of a block of code in a single thread.

Scenarios where concatenation is applicable: when there are a large number of operations in the program that do not require the CPU (IO), concatenation is applicable;

greenlet

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from greenlet import greenlet
def test1():
print 12
()
print 34
()
def test2():
print 56
()
print 78
gr1 = greenlet(test1)
gr2 = greenlet(test2)
() 

gevent

import gevent
def foo():
print('Running in foo')
(0)
print('Explicit context switch to foo again')
def bar():
print('Explicit context to bar')
(0)
print('Implicit context switch back to bar')
([
(foo),
(bar),
]) 

Automatically switches when an IO operation is encountered:

from gevent import monkey; monkey.patch_all()
import gevent
import urllib2
def f(url):
print('GET: %s' % url)
resp = (url)
data = ()
print('%d bytes received from %s.' % (len(data), url))
([
(f, '/'),
(f, '/'),
(f, '/'),
]) 

The above is a small introduction to the knowledge of processes, threads, and co-programs in Python, I hope it will help you!