Python concurrent programming Multi-Threading

Source: Internet
Author: User
Tags mutex processing text

One, threading theory 1. What is a thread

The concept of multithreading (that is, multiple control threads) is that there are multiple threads in a process, and multiple threads share the process's address space, which is equivalent to a workshop with multiple pipelines, sharing a workshop resource.

Therefore, a process is simply used to centralize resources together (a process is just a resource unit, or a resource collection), and the thread is the executing unit on the CPU.

2. The difference between a process and a thread
    • Multiple threads within the same process share address resources within the process

    • The cost of creating a thread is much less than the cost of creating the process (creating a process, creating a workshop, involving the application space, and building at least one pipeline within that space, but creating a thread that creates a pipeline in a single workshop without requesting space, so the creation cost is small)

3. Examples of multithreaded applications

Open a word processing software process, the process must do more than one thing, such as listening to keyboard input, processing text, automatically save the text to the hard disk, the three tasks are the same piece of data, and therefore can not be used multi-process. Only in one process can open three threads concurrently, if it is a single thread, it can only be, keyboard input, can not handle text and auto-save, automatically save the text can not be entered and processed.

Two ways to turn on the thread

Way One:

import time, randomfrom threading import Threaddef task(name):    print('%s is running' %name)    time.sleep(random.randrange(1, 3))    print('%s running end' %name)if __name__ == '__main__':    t1 = Thread(target=task, args=('gudon', ))    t1.start()    print('主线程。。。')        ---------------------------打印结果-----------------------------gudon is running主线程。。。gudon running end

Way two:

import time, randomfrom threading import Threadclass MyThread(Thread):    def __init__(self, name):        super().__init__()        self.name = name    def run(self):        print('%s is running' %self.name)        time.sleep(random.randrange(1,3))        print('%s running end' %self.name)if __name__ == "__main__":    t1 = MyThread('Astro')    t1.start()    print('主线程......')    ---------------------------打印结果-----------------------------Astro is running主线程......Astro running end

Multprocess, threading two modules in the use of a very similar way

Ii. differences between processes and threads 1. The cost of the thread is much less than the cost of the open process

Process:

import time, randomfrom threading import Threadfrom multiprocessing import Processdef task(name):    print('%s is running' %name)    time.sleep(random.randrange(1, 3))    print('%s running end' %name)if __name__ == '__main__':    p = Process(target=task, args=('Astro', ))    p.start() # p.start ()将开启进程的信号发给操作系统后,操作系统要申请内存空间,让好拷贝父进程地址空间到子进程,开销远大于线程    print('主...........')    ---------------------------【进程】打印结果-----------------------------主...........Astro is runningAstro running end

Thread:

import time, randomfrom threading import Threadfrom multiprocessing import Processdef task(name):    print('%s is running' %name)    time.sleep(random.randrange(1, 3))    print('%s running end' %name)if __name__ == '__main__':    t1 = Thread(target=task, args=('Astro', ))    t1.start() #几乎是t.start ()的同时就将线程开启了,线程的创建开销要小鱼进程创建的开销    print('主...........')    ---------------------------【线程】打印结果-----------------------------Astro is running主...........Astro running end
2. Multiple threads within the same process share the process's address space
from threading import Threadfrom multiprocessing import Processn = 100def task():    global n    n = 0if __name__ == "__main__":    p1 = Process(target=task)    p1.start()    p1.join()    print('主 %s' %n)      ---------------------------打印结果-----------------------------主 100

Child process P1 creation, will be the main process of the data copied one copy, the process data does not affect each other, so the child process P1 in n=0, only the child process n changed, the main process n is not affected, that is, the address space between the process is isolated

from threading import Threadfrom multiprocessing import Processn = 100def task():    global n    n = 0if __name__ == "__main__":    t1 = Thread(target=task)    t1.start()    t1.join()    print('主 %s' %n)---------------------------打印结果-----------------------------主 0

Share in-process data between threads within the same process, so 0

3. PID

The PID is the process ID, which is the ID number.

multiple processes, each with a different PID:

from multiprocessing import Process, current_processfrom threading import Threadimport osdef task():   # print('子进程...', current_process().pid)  # 也可以使用 os.getpid()或 current_process().pid 来查看当前进程的pid,os.getppid() 可以查看当前进程的父进程的pid    print('子进程PID:%s  父进程的PID:%s' % (os.getpid(), os.getppid()))if __name__ == '__main__':    p1 = Process(target=task)    p1.start()    print('主线程', current_process().pid)        ---------------------------打印结果-----------------------------主线程 808子进程PID:7668  父进程的PID:808

Open multiple threads under the main process, each with the same PID as the main process

from threading import Threadimport osdef task():    print('子线程pid:',os.getpid())if __name__ == '__main__':    t1 = Thread(target=task, )    t1.start()    print('主线程pid:', os.getpid())---------------------------打印结果-----------------------------子线程pid: 9084主线程pid: 9084
Third, other properties or methods of the thread object
  Thread Instance object method # IsAlive (): Returns whether the thread is active.  # getName (): Returns the thread name. # setName (): Sets the thread name.  Some of the methods provided by the threading module are: # Threading.currentthread (): Returns the current thread variable. # threading.enumerate (): Returns a list that contains the running thread.  Running refers to threads that do not include pre-and post-termination threads until after the thread has started and ends. # Threading.activecount (): Returns the number of running threads with the same result as Len (Threading.enumerate ()). 
from threading import Thread, currentThread,active_count,enumerateimport timedef task():    print('%s is running '%currentThread().getName())    time.sleep(2)    print('%s is done' %currentThread().getName())if __name__ == "__main__":    t = Thread(target=task, )    # t = Thread(target=task, name='子线程001')  # 也可以在这里改子线程名字    t.start()    # t.setName('子线程001')    t.join()    currentThread().setName('主线程')    print(active_count())  # 返回正在运行的线程数量    print(enumerate())  # [<_MainThread(主线程, started 6904)>]     默认为:[<_MainThread(MainThread, started 6904)>]        ---------------------------打印结果-----------------------------子线程001 is running 子线程001 is done1[<_MainThread(主线程, started 6432)>]
Iv. Daemon Threads and mutexes 1. Daemon Threads

Whether it is a process or a thread, follow: Guardian xxx will wait for the main xxx to be destroyed after the completion of the operation

1, for the main process, run complete refers to the main process code is finished running

主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,

2, to the main thread, said, run complete refers to the main thread is in the process of all the non-daemon threads run complete, the main thread is run complete

主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。
from threading import Threadimport timedef sayHi(name):    time.sleep(2)    print('%s say Hello')if __name__ == '__main__':    t = Thread(target=sayHi, args=('Astro', ))    t.setDaemon(True)  # 设置为守护线程, t.daemon = True 也可以    t.start()    print('主线程')    print(t.is_alive())    ----------------------执行结果---------------------------主线程True

t.start(), the system creates a sub-thread immediately, but since the 2 second of the child thread is time.sleep(2) already a long time for the computer, the

print('主线程')print(t.is_alive())

After execution, the main thread ends, and the child thread is followed by the end, because we set the child thread as the daemon thread

Look at an example:

def foo():    print('foo runing..')    time.sleep(1)    print('foo end')def bar():    print('bar running..')    time.sleep(3)    print('bar end')if __name__ == '__main__':    t1 = Thread(target=foo, )    t2 = Thread(target=bar, )    t1.setDaemon(True)    t1.start()    t2.start()    print('main.......')    ----------------------执行结果---------------------------   foo runing..bar running..main.......foo endbar end

T1 is the daemon, t1.start() after that, execute the Foo function immediately, and thentime.sleep(1)

t2.start()the thread is turned on, and after the bar function is executedtime.sleep(3)

In 3 seconds, the main thread is executed, print(‘main......‘) and then the main thread task has completed, but because the child thread T2 is not finished, T2 non-daemon thread, the main thread also needs to wait for the non-daemon thread T2 run completed before the end, so in the time of waiting for T2 end, T1 After the thread executes, T1 only sleep for 1 seconds, enough time for T1 to execute first.

Then T2 three seconds to execute the rest of his own.

2. Mutual exclusion Lock
from threading import Thread, Lockimport timen = 100def task(mutex):    global n    mutex.acquire()  # 加互斥锁    temp = n    time.sleep(0.1)    n = temp - 1    mutex.release()if __name__ == '__main__':    mutex = Lock()    t_list = []    for i in range(100):        t = Thread(target=task, args=(mutex, ))        t_list.append(t)        t.start()    for t in t_list:        t.join()    print('main....',n) ----------------------执行结果---------------------------main.... 0

If the mutex is not added, the result ismain.... 99

Because, in the loop t.start() , 100 lines of routines are created immediately, and then in the function, 100 threads of temp are assigned values in order to 100, so n = temp - 1 only the loop is assigned a value of 99.

In addition, the mutex only guarantees the local serial, not the same as the join

V. GIL GLOBAL Interpreter Lock

Run this Code

import os, timeprint(os.getpid())  # 5132time.sleep(1000)

Then CMD to seetasklist |findstr python

Results:

python.exe                    5132 Console                    1      9,568 K

Python concurrent programming Multi-Threading

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.