Python learning notes: threads, processes, collaborations.

1, Thread

1. Definition: thread is the smallest unit that the operating system can perform operation scheduling. It is included in the process and is the actual operation unit of the process. A thread is a single sequential control flow in the process. Multiple threads can be concurrent in a process, and each thread can execute different tasks in parallel. Simple understanding: thread is a set of instructions through which the operating system calls hardware.

2. All threads in the same thread share the same memory space resource,

 

2, Progress

1. Definition: the collection of resource management and call of a program is a process, such as the scheduling and management of network card, memory and hard disk by QQ. For the operating system, a process is a unified whole. The process operation CPU needs to create a thread first. The process itself is a collection of resources, and its execution depends on threads.

 

3, The difference between thread and process

1. Threads of the same process share memory space, including data exchange and communication, but memory between different processes is independent

2. The child processes clone the data of a parent process. The child processes are independent of each other, cannot access each other, and cannot share the data.

3. If two processes want to communicate, they must be realized through an intermediate process agent.

4. A thread can operate other threads in the same process, but a process can only operate subprocesses

5. The modification of the main thread may affect other sub threads because they share memory data, but the modification of the main process will not affect other sub processes.

 

4, Multithreaded code:

import threading
import time


class MyThread(threading.Thread):
    """
    # Start a thread by customizing a subclass
    """

    def __init__(self, n):
        super(MyThread, self).__init__()
        self.n = n

    def run(self):
        print("Hello,%s" % self.n)
        time.sleep(2)


start_time = time.time()
thread_list = []

# Start 50 threads
for i in range(50):
    t1 = MyThread("t%s" % i)
    t1.start()
    thread_list.append(t1)
# Wait for all threads to finish before the main thread continues
for i in thread_list:
    i.join()

print("Total execution time:%s" % float(time.time() - start_time))

 

5, Global interpreter lock (GIL)

1. Definition: GIL is a technical term in the most popular CPython interpreter (commonly known as Python). It is translated into global interpreter lock in Chinese, which is essentially similar to Mutex of operating system (i.e. Mutex, which means you can't modify when I modify, that is, lock)

2. Function: every Python thread executed in CPython interpreter will lock itself first to prevent other threads from executing, so that only one thread is executed by one CPU at the same time. Of course, CPython cannot tolerate a thread to monopolize the interpreter all the time. The check interval mechanism will release the global lock of the previous thread to execute the next thread after a period of time, so as to achieve the purpose of executing threads in turn. In this way, what users see is "pseudo" parallelism, that is, python threads are executing alternately to simulate truly parallel threads.

3. The introduction of GIL by CPython can avoid the complicated competition risk problems like memory management to the greatest extent. With GIL, it does not mean that thread safety need not be considered, because even if GIL only allows one Python thread to execute, don't forget that Python also has a preemptive mechanism like check interval. Therefore, we need to introduce thread lock mechanism to ensure that only one thread modifies data at the same time.

 

 

4. The code of thread lock is as follows

import threading
import time

num = 0

lock_obj = threading.Lock()


def run():
    # Apply lock, make other threads unable to enter
    lock_obj.acquire()
    global num
    time.sleep(1.1)
    num = num + 1
    # Unlock. After unlocking, other threads can come in
    lock_obj.release()


t_list = []
start_time = time.time()
# Start 1000 threads
for i in range(100):
    t1 = threading.Thread(target=run)
    t1.start()
    t_list.append(t1)

for i in t_list:
    i.join()

time.sleep(3)
print("num:%d" % num)
print("time:%f" % float(time.time() - start_time))

 

6, Recursive lock:

1. Definition: one lock sleeve and another lock form a lock cycle. In this case, recursive lock RLOCK is used

import threading, time

def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num

def run2():
    print("grab the second part data")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2

def run3():
    lock.acquire()
    res = run1()
    print('--------between run1 and run2-----')
    res2 = run2()
    lock.release()
    print(res, res2)

num, num2 = 0, 0
# If you use Lock()There will be infinite cycles, and no specific key can be found to open the lock. If RLock No, if multiple locks are nested, recursive locks must be used
lock = threading.Lock()
for i in range(1):
    t = threading.Thread(target=run3)
    t.start()

while threading.active_count() != 1:
    print("Number of threads currently active:",threading.active_count())
else:
    print('----all threads done---')
    print("Printing num and num2: ",num, num2)

 

7, Semaphore (semaphore)

1. At most several threads are allowed to enter the execution at the same time, one for each coming out, while maintaining the preset maximum allowable number of threads.

import threading, time


def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread: %s\n" % n)
    semaphore.release()

if __name__ == '__main__':
    semaphore = threading.BoundedSemaphore(5)  # Allow up to 5 threads to run at the same time
    for i in range(22):
        t = threading.Thread(target=run, args=(i,))
        t.start()
while threading.active_count() != 1:
    pass  # print threading.active_count()
else:
    print('----all threads done---')
    #print(num)

 

8, Event:

1. Definition: realize the interaction between threads by identifying bits and states. In short, it is a flag bit. There are only two states. One is setting (Event.set()), and there has been no setting (Event.clear()).

2. The following code implements a simple event: one thread controls the traffic light, and the other thread controls the car. When the traffic light is red, the car stops, and when it is green, the car drives

import time
import threading


event = threading.Event()

def lighter():
    count = 0
    event.set()  # Green light is set for the initial identification bit
    while True:
        if 5 < count < 10:  # Change to red light
            event.clear()  # Clear the sign
            print("\033[41;1mred light is on....\033[0m")
        elif count > 10:
            event.set()  # Turn green
            count = 0
        else:
            print("\033[42;1mgreen light is on....\033[0m")
        time.sleep(1)
        count += 1


def car(name):
    while True:
        if event.is_set():  # Green light
            print("[%s] running..." % name)
            time.sleep(1)
        else:
            print("[%s] sees red light , waiting...." % name)
            event.wait()
            print("\033[34;1m[%s] green light is on, start going...\033[0m" % name)


light = threading.Thread(target=lighter, )
light.start()

car1 = threading.Thread(target=car, args=("Tesla",))
car1.start()

3. The Event class has two methods: wait() to be set, and isset() to determine whether it is set

Tags: Python network

Posted on Thu, 14 May 2020 06:19:09 -0400 by stuartbrown20