Thirteen, TCP server concurrency
13.1, the server requirements
1, a fixed IP and port
2,24-hour service
3, supports concurrent
13.2 Code
import socket from threading import Thread server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) def talk(conn): while True: try: data = conn.recv(1024) if not data: break print(data.decode('utf-8')) conn.send(data.upper()) except ConnectionResetError as e: print(e) break conn.close() while True: conn, addr = server.accept() t = Thread(target=talk, args=(conn,)) t.start()
Fourteen, GIL (Global Interpreter Lock)
14.1, Cpython interpreter
1, GIL is a unique concept interpreter Cpython
2, in Cpython in the same process to open multiple threads, the same time only one thread of execution, unable to take advantage of multi-core advantage
14.2 reason for the existence of GIL
Within a python process, all data sharing, including the interpreter code. All processes must access the interpreter to execute code, including garbage collection process. Therefore, only by interpreter code lock is
To avoid the data is garbage collection mechanism at the outset.
14.3, process and multi-threaded option
14.3.1, process and multithreading features
1, the process can take advantage of multi-core, but the overhead
2, thread overhead small, we can not take advantage of multi-core advantage
14.3.2 Conclusion
1, applied to multi-threaded I / O-intensive tasks, because no amount of CPU the face of I / O is blocked, open multi-process but takes more memory.
2, multi-process used in compute-intensive tasks, and more nuclear energy effectively enhance the computing speed.
XV deadlock with recursive lock
15.1 deadlock
Two or more processes or threads in the implementation process, due to competition for resources caused by the phenomenon of waiting for each other. If there is no external force, they can not promote it.
from threading import Thread, Lock
import time
mutexA = Lock()
mutexB = Lock()
class MyThread(Thread):
def run(self):
self.func1()
self.func2()
def func1(self):
mutexA.acquire()
print(1, self.name)
mutexB.acquire()
print(2, self.name)
mutexB.release()
print(3, self.name)
mutexA.release()
print(4, self.name)
def func2(self):
mutexB.acquire()
print(5, self.name)
time.sleep(1)
mutexA.acquire()
print(6, self.name)
mutexA.release()
print(7, self.name)
mutexB.release()
print(8, self.name)
for i in range(2):
t = MyThread()
t.start()
1 Thread-1
2 Thread-1
3 Thread-1
4 Thread-1
5 Thread-1
1 Thread-2
15.2, recursive lock RLock
It can be the first person to grab the lock acquire and release multiple times
Each acquire a lock count by one
Each time the lock release count by 1
As long as the lock count is not 0, the other thread can grab locks
Avoid deadlock
from threading import Thread, RLock
import time
mutexA = mutexB = RLock()
class MyThread(Thread):
def run(self):
self.func1()
self.func2()
def func1(self):
mutexA.acquire()
print(1, self.name)
mutexB.acquire()
print(2, self.name)
mutexB.release()
print(3, self.name)
mutexA.release()
print(4, self.name)
def func2(self):
mutexB.acquire()
print(5, self.name)
time.sleep(1)
mutexA.acquire()
print(6, self.name)
mutexA.release()
print(7, self.name)
mutexB.release()
print(8, self.name)
for i in range(2):
t = MyThread()
t.start()
1 Thread-1
2 Thread-1
3 Thread-1
4 Thread-1
5 Thread-1
6 Thread-1
7 Thread-1
8 Thread-1
1 Thread-2
2 Thread-2
3 Thread-2
4 Thread-2
5 Thread-2
6 Thread-2
7 Thread-2
8 Thread-2
XVI semaphore
1, the semaphore is locked, if the specified semaphore is 5, the same time there are five tasks to get the lock to perform.
from threading import Thread, Semaphore import threading import time def func(): s.acquire() print(threading.current_thread().getName()) time.sleep(3) s.release() if __name__ == '__main__': s = Semaphore(5) for i in range(10): t = Thread(target=func) t.start()
Thread-1 Thread-2 Thread-3 Thread-4 Thread-5 Thread-7 Thread-8 Thread-6 Thread-9 Thread-10