The _thread module of python multithreaded programming

In addition to deriving threads, the _thread module also provides basic synchronization data structures, also known as lock objects (lock objects, also known as primitive locks, simple locks, mutexes, mutexes, and binary semaphores).

The following are commonly used thread functions:

function describe
start_new_thread(function,args,kwargs=None) Forks a new thread to execute function with the given args and optional kwargs
allocate_lock() Allocate a LockType object
exit() exit thread instruction
Method of LockType lock object
acquire(wait=None) try to acquire the lock object
locked() Return True if the lock object is acquired, otherwise return False
release() release lock

The core function of the _thread module is start_new_thread(). Specifically used to spawn new threads.

We slightly modified the onethr.py file in the previous section:

#!/usr/bin/env python

import _thread
from time import sleep,ctime

def loop0():
    print('开始循环0次在:',ctime())
    sleep(4)
    print('结束循环0次在:',ctime())

def loop1():
    print('开始循环1次在:',ctime())
    sleep(2)
    print('结束循环1次在:',ctime())

'''    
def main():
    print('开始于:',ctime())
    loop0()
    loop1()
    print('所有的任务都完成于:',ctime())
''' 

def main():
    print('starting at:', ctime())
    _thread.start_new_thread(loop0, ())
    _thread.start_new_thread(loop1, ())
    sleep(6)
    print('all done at:', ctime())
    
if __name__ =='__main__':
    main(

Execute the script three times, the result:

PS C:\Users\WC> python E:\Python3.6.3\workspace\mtsleepA.py
starting at: Mon Mar 26 21:56:10 2018
开始循环1次在: Mon Mar 26 21:56:10 2018
开始循环0次在: Mon Mar 26 21:56:10 2018
结束循环1次在: Mon Mar 26 21:56:12 2018
结束循环0次在: Mon Mar 26 21:56:14 2018
all done at: Mon Mar 26 21:56:16 2018
PS C:\Users\WC> python E:\Python3.6.3\workspace\mtsleepA.py
starting at: Mon Mar 26 22:00:43 2018
开始循环0次在: Mon Mar 26 22:00:43 2018
开始循环1次在: Mon Mar 26 22:00:43 2018
结束循环1次在: Mon Mar 26 22:00:45 2018
结束循环0次在: Mon Mar 26 22:00:47 2018
all done at: Mon Mar 26 22:00:49 2018
PS C:\Users\WC> python E:\Python3.6.3\workspace\mtsleepA.py
starting at: Mon Mar 26 22:00:56 2018
开始循环0次在: Mon Mar 26 22:00:56 2018
开始循环1次在: Mon Mar 26 22:00:56 2018
结束循环1次在: Mon Mar 26 22:00:58 2018
结束循环0次在: Mon Mar 26 22:01:00 2018
all done at: Mon Mar 26 22:01:02 2018

As can be seen from the above code, start_new_thread() must contain two parameters, even if the function to be executed does not require parameters, an empty tuple must be passed.

We noticed that the start order of loop0 or loop1 can be out of order; loop0 and loop1 are executed at the same time; loop1 ends before loop0; the whole program takes 6 seconds in total.

We can say that loop0 and loop1 are executed concurrently.

We added a sleep(6) statement to the main program (in fact, the main thread). This is actually to avoid the problem that the loop0 and loop1 threads have not ended when the main program ends. This is also a thread synchronization mechanism of the _thread module.

However, we want to say that using sleep() for thread synchronization is unreliable, which is also a drawback of _thread.

At this time, we can use the lock mechanism to implement the corresponding thread management, and at the same time improve the implementation of the individual loop function:

import _thread
from time import sleep, ctime
#不再把4秒和2秒硬性的编码到不同的函数中,而是使用唯一的loop()函数,并把这些常量放进列表loops中
loops=[4,2]
#代替了之前的loop*()函数,三个参数分别代表了处于第几个循环中,睡眠时间和锁对象。每个循环执行到最后一句的时候,释放锁对象,告诉主线程该线程已完成
def loop(nloop,sec,lock):
    print('开始循环',nloop,'在:',ctime())
    sleep(sec)
    print('循环',nloop ,'结束于:',ctime())
    lock.release()
    
def main():
    print('开始于:',ctime())
    locks=[]
    nloops=range(len(loops))
    
    #第一个for循环中,创建了一个锁的列表,通过thread.allocate_lock()方法得到锁对象,再通过acquire()方法取到锁(相当于把锁锁上),取到之后就可以把它添加到锁列表locks中。
    for i in nloops:
        lock=_thread.allocate_lock()
        lock.acquire()
        locks.append(lock)
    #第二个for循环中,主要用于派生线程。每个线程都会调用loop()函数,并传递循环号、睡眠时间以及用于该线程的锁。  
    for i in nloops:
        _thread.start_new_thread(loop,(i,loops[i],locks[i]))
    #第三个for循环,按照顺序检查每个锁。每个线程执行完毕后,都会释放自己的锁对象。这里使用忙等待,让主线程等所有的锁都释放后才继续执行
    for i in nloops:
        while locks[i].locked():
            pass
    print('所有的任务完成于:',ctime())
    
if __name__ =='__main__':
    main()

Results of the:

Started loop 1 at: Mon Mar 26 22:49:25 2018
Started loop 0 at: Mon Mar 26 22:49:25 2018
Loop 1 ended on: Mon Mar 26 22:49:27 2018
Loop 0 ended on: Mon Mar 26 22:49:29 2018
All tasks completed on: Mon Mar 26 22:49:29 2018

In the above results, except that the two loops of the table name are executed concurrently, the entire program takes 4 seconds instead of the previous 6 seconds.

Guess you like

Origin blog.csdn.net/m0_59485658/article/details/129336142