Thread theory
What is a thread
Thread (English: thread) is the smallest unit that the operating system can schedule operations. It is included in the process and is the actual operation unit in the process. A thread refers to a single sequential control flow in a process. Multiple threads can be concurrent in a process, and each thread executes different tasks in parallel.
Thread appearance
Relationship between process and thread
1. Address space and other resources (such as open files): processes are independent and shared among threads of the same process. Threads within one process are not visible to other processes.
2. Communication: interprocess communication IPC. Threads can directly read and write process data segments (such as global variables) for communication - process synchronization and mutual exclusion are required to ensure data consistency.
3. Scheduling and switching: thread context switching is much faster than process context switching.
4. In a multithreaded operating system, a process is not an executable entity.
Thread characteristics
1. Multiple threads share the address space of a process
2. Threads are lighter than processes, and threads are easier to create revocable than processes. In many operating systems, creating a thread is 10-100 times faster than creating a process. This feature is very useful when a large number of threads need dynamic and rapid modification
3. If multiple threads are cpu intensive, there is no performance enhancement, but if there is a large amount of computing and a large amount of I/O processing, having multiple threads allows these activities to overlap each other, which will speed up the execution of the program.
4. In a multi cpu system, in order to maximize the use of multi-core, you can start multiple threads, which is much less expensive than starting processes. (this does not apply to python)
There are two ways to create threads
Mode 1:
from threading import Thread import time def test(name): time.sleep(2) print('%s say hello' %name) if __name__ == '__main__': t=Thread(target=test,args=('xie',)) t.start() print('Main thread')
Mode 2:
from threading import Thread import time class MyThread(Thread): def __init__(self,name): super().__init__() self.name=name def run(self): time.sleep(2) print('%s say hello' % self.name) if __name__ == '__main__': t = MyThread('xie') t.start() print('Main thread')
Other methods in the thread module
t.isAlive(): Returns whether the thread is active
t.getName(): returns the thread name
t.setName(): sets the thread name
threading.currentThread(): returns the current thread variable
threading.enumerate(): returns a list of running threads. Running refers to the thread after starting and before ending, excluding the threads before starting and after termination
threading.activeCount(): returns the number of running threads, which is the same as len(threading.enumerate())
Daemon thread
Stops and is recycled as the main thread finishes running. For the main thread, running completion means that all non daemon threads in the process where the main thread is located have finished running, and the main thread is considered to have finished running.
from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") t1=Thread(target=foo) t2=Thread(target=bar) t1.daemon=True t1.start() t2.start() print("main-------") # Output sequence: # 123 # 456 # main------- # end123 # end456
mutex
Simulate 100 people grabbing tickets at the same time. Without locking, the data is easy to be confused, which is likely to cause the final data to be inconsistent with the logic.
from threading import Thread import time def grab(): global n temp=n time.sleep(0.1) n=temp-1 if __name__ == '__main__': n=100 l=[] for i in range(100): t=Thread(target=grab) l.append(p) t.start() for t in l: t.join() print(n) #The result could be 99
We need to Lock to ensure the security of data, that is, change parallel to serial to ensure that only one thread performs data operations at the same time. threading is similar to multiprocess and also has Lock.
from threading import Thread,Lock import time def grab(): global n lock.acquire() temp=n time.sleep(0.1) n=temp-1 lock.release() if __name__ == '__main__': lock=Lock() n=100 l=[] for i in range(100): t=Thread(target=grab) l.append(t) t.start() for t in l: t.join() print(n) # The result must be 0, which changes from concurrent execution to serial execution, sacrificing execution efficiency and ensuring data security
TCP server implements concurrency
Concurrency can be achieved as long as multithreading is set up on the server to receive access from multiple clients
import socket from threading import Thread from multiprocessing import Process server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) def talk(sock): while True: try: data = sock.recv(1024) if len(data) == 0: break print(data.decode('utf8')) sock.send(data + b'server end') except ConnectionResetError as e: print(e) break sock.close() while True: sock, addr = server.accept() print(addr) # Set up multi process or multi thread t = Thread(target=talk, args=(sock,)) t.start()