掌握并发编程3

十三、TCP 服务端实现并发

  13.1、服务端要求

    1、有固定 IP 和 port

    2、24 小时不间断提供服务

    3、支持并发

  13.2、代码

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()

十四、GIL(全局解释器锁)

  14.1、Cpython 解释器

    1、GIL 是 Cpython 解释器特有的概念

    2、在 Cpython 中,同一进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势

  14.2、GIL 存在的原因

    在一个 python 进程内,所有数据共享,包括解释器的代码。所有进程都要访问解释器的代码去执行,包括垃圾回收进程。因此只有通过为解释器代码加锁

    来避免数据在一开始就被垃圾回收机制执行。

  14.3、进程与多线程的选择

    14.3.1、进程与多线程的特点

      1、进程可以利用多核,但开销大

      2、线程开销小,无法利用多核优势

    14.3.2、结论

      1、多线程应用于 I / O 密集型任务,因为再多的 CPU 面对 I / O 都是阻塞,开多进程反而耗费更多内存。

      2、多进程应用于计算密集型任务,多核能有效提升计算速度。

十五、死锁现象与递归锁

  15.1、死锁现象

    两个或两个以上的进程或线程在执行过程中,因争夺资源而造成互相等待的现象。若无外力作用,它们都无法推进下去。

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、递归锁 RLock

    可以被第一个抢到该锁的人多次的 acquire 和 release

    每 acquire 一次锁的计数加 1

    每 release 一次锁的计数减 1

      只要锁的计数不为 0,其他线程都不能抢锁

    避免了死锁现象

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

十六、信号量

  1、信号量也是锁,如果指定信号量为5,则同一时间有5个任务拿到锁去执行。

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

猜你喜欢

转载自www.cnblogs.com/binyuanxiang/p/11360524.html
今日推荐