This article mainly introduces the simple use of Python multi-threading, locks, and event event mechanisms. Now I share it with you and give it as a reference. Let’s take a look together
Threads and processes
1. Threads share the address space of the process that created it, and the process has its own The address space
2. Threads can access all data of the process, and threads can access each other
3. The data between threads are independent
4. The child process copies the thread's data
5. The child process is independent after it is started. The parent process can only kill the child process but cannot exchange data
6. Modify the data in the thread. All will affect other threads, but changes to the process will not affect the child process
threading.Thread
Thread is a threading module One of the most important classes in , you can use it to create threads. There are two ways to create a thread: one is to inherit the Thread class and override its run method; the other is to create a threading.Thread object and pass the callable object as a parameter in its initialization function (__init__) enter.
Let’s first look at an example of creating a thread by inheriting the threading.Thread class:
import threading import time class MyThread(threading.Thread): def __init__(self, arg): # super(MyThread, self).__init__() # 新式类继承原有方法写法 threading.Thread.__init__(self) self.arg = arg def run(self): time.sleep(2) print(self.arg) for i in range(10): thread = MyThread(i) print(thread.name) thread.start()
Another way to create a thread:
import threading import time def process(arg): time.sleep(2) print(arg) for i in range(10): t = threading.Thread(target=process, args=(i,)) print(t.name) t.start()
The Thread class also defines the following common methods and attributes:
Thread.getName() Gets the thread name
Thread.setName() Sets the thread name
Thread.name Thread name
Thread.ident Gets the identifier of the thread. The thread identifier is a non-zero integer. This attribute is only valid after the start() method is called. Otherwise, it only returns None
to determine whether the thread is active. From the time the start() method is called to start the thread until the run() method is completed or interrupted due to an unhandled exception, the thread is active
Thread.is_alive()
Thread.isAlive ()
Thread.join([timeout]) Calling Thread.join will block the calling thread until the called thread ends or times out. The parameter timeout is a numeric type, indicating the timeout time. If this parameter is not provided, the calling thread will block until the called thread ends
Python GIL (Global Interpreter Lock)
GIL is not a feature of Python, it is a concept introduced when implementing the Python parser (CPython). Just like C is a set of language (grammar) standards, but it can be compiled into executable code using different compilers. Famous compilers such as GCC, INTEL C, Visual C, etc. The same is true for Python. The same piece of code can be executed through different Python execution environments such as CPython, PyPy, and Psyco. For example, JPython does not have GIL. However, CPython is the default Python execution environment in most environments. Therefore, in the concept of many people, CPython is Python, and they take it for granted that GIL is a defect of the Python language. So let’s be clear here: GIL is not a feature of Python, and Python does not need to rely on GIL at all.
Use of thread lock:
# 锁:GIL 全局解释器 它是为了保证线程在运行过程中不被抢占 number = 0 lock = threading.RLock() # 创建锁 def run(num): lock.acquire() # 加锁 global number number += 1 print(number) time.sleep(2) lock.release() # 释放锁 for i in range(10): t = threading.Thread(target=run, args=(i, )) t.start()
##Join & Daemon
class MyThread1(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): print("thread start") time.sleep(3) print('thread end') print('main start') thread1 = MyThread1() # thread1.setDaemon(True) # 设置子线程是否跟随主线程一起结束 thread1.start() time.sleep(1) print('satrt join') # thread1.join() # 使主线程阻塞,直至子线程运行完毕再继续主线程 print('end join')
def run(n): print('[%s]------running----\n' % n) time.sleep(2) print('--done--') def main(): for i in range(5): t = threading.Thread(target=run, args=[i,]) t.start() # t.join() print('starting thread', t.getName()) m = threading.Thread(target=main,args=[]) # m.setDaemon(True) # 将主线程设置为Daemon线程,它退出时,其它子线程会同时退出,不管是否执行完任务 m.start() # m.join() # 使主线程阻塞,直至子线程运行完毕再继续主线程 print("---main thread done----")
Multiple threads can be started under one process, and multiple threads share the memory space of the parent process, which means that each thread can access the same data. At this time, if two threads want to modify the same data at the same time , what will happen?
num = 100 # 设定一个共享变量 def subNum(): global num # 在每个线程中都获取这个全局变量 print('--get num:', num) time.sleep(2) num -= 1 # 对此公共变量进行-1操作 thread_list = [] for i in range(100): t = threading.Thread(target=subNum) t.start() thread_list.append(t) for t in thread_list: # 等待所有线程执行完毕 t.join() print('final num:', num)
# 加锁版本 def subNum(): global num # 在每个线程中都获取这个全局变量 print('--get num:', num) time.sleep(1) lock.acquire() # 修改数据前加锁 num -= 1 # 对此公共变量进行-1操作 lock.release() # 修改后释放 num = 100 # 设定一个共享变量 thread_list = [] lock = threading.Lock() # 生成全局锁 for i in range(100): t = threading.Thread(target=subNum) t.start() thread_list.append(t) for t in thread_list: # 等待所有线程执行完毕 t.join() print('final num:', num)
##The difference between Rlock and Lock:
RLock allows to be acquired multiple times in the same thread. But Lock does not allow this. Otherwise, an infinite loop will occur, and the program will not know which lock to unlock. Note: If you use RLock, acquire and release must appear in pairs, that is, acquire is called n times, and release must be called n times to truly release the occupied lock
Events
Python provides the Event object for inter-thread communication. It is a signal flag set by the thread. If the signal flag is true, other threads wait until the signal is contacted.
The Event object implements a simple thread communication mechanism. It provides setting signals, clearing signals, waiting, etc. for realizing communication between threads.
event = threading.Event() Create an event
event.set()
Use the set() method of Event to set the Event object The internal signal flag is true. The Event object provides the isSet() method to determine the status of its internal signal flags.
When the set() method of the event object is used, the isSet() method returns true
2 Clear signal
event.clear()
使用Event对象的clear()方法可以清除Event对象内部的信号标志,即将其设为假,当使用Event的clear方法后,isSet()方法返回假
3 等待
event.wait()
Event对象wait的方法只有在内部信号为真的时候才会很快的执行并完成返回。当Event对象的内部信号标志位假时,
则wait方法一直等待到其为真时才返回。也就是说必须set新号标志位真
def do(event): print('start') event.wait() print('execute') event_obj = threading.Event() for i in range(10): t = threading.Thread(target=do, args=(event_obj,)) t.start() event_obj.clear() inp = input('输入内容:') if inp == 'true': event_obj.set()
相关推荐:
Python多线程中阻塞(join)与锁(Lock)使用误区解析
The above is the detailed content of Detailed explanation of the simple use of Python multi-threading, locks, and event event mechanisms. For more information, please follow other related articles on the PHP Chinese website!