线程的其他知识点

---恢复内容开始---

不使用socketserver模块实现 tcp协议服务端的并发

import socket
from threading import Thread

s = socket.socket()

s.bind(('127.0.0.1', 56984))
s.listen(5)


def server_while(conn):
    while True:
        try:
            data = conn.recv(1024)
            print(data.decode('utf-8'))
            conn.send(data.upper())
        except ConnectionResetError as c:
            print(c)
            break
    conn.close()

if __name__ == '__main__':
    while True:
        conn, addr = s.accept()
        t = Thread(target=server_while, args=(conn,))
        t.start()
服务端
import socket

client = socket.socket()
client.connect(('127.0.0.1',56984))

while True:
    client.send(b'sdjflaasdfad')
    data = client.recv(1024)
    print(data)
服务端

GIL全局解释器锁

ps:python解释器有很多种 最常见的就是Cpython解释器

GIL本质也是一把互斥锁:将并发变成串行牺牲效率保证数据的安全    用来阻止同一个进程下的多个线程的同时执行(同一个进程内多个线程无法实现并行但是可以实现并发

   问 python的多线程没法利用多核优势 是不是就是没有用了?   答  python的多线程到底有没有用需要看情况而定 并且肯定是有用的  一般 多进程+多线程配合使用

GIL的存在是因为CPython解释器的内存管理不是线程安全的

什么是内存管理(代码申请代码释放 相当于 with open close)

垃圾回收机制 

  1.引用计数:内存中的数据如果没有任何的变量名与其有绑定关系,那么会被自动回收

  2.标记清除:当内存快要被某个应用程序占满的时候,会自动触发

  3.分代回收:根据值得存活时间的不同,划为不同的等级,等级越高垃圾回收机制扫描的频率越低

继续问  python的多线程没法利用多核优势 是不是就是没有用了?

研究python的多线程是否有用需要分情况讨论
  四个任务 计算密集型的 
    单核情况下
      开线程更省资源 (单核的话 进程 和 线程 都可以并发 但是 线程 更省资源)
    多核情况下   一次任务 10秒 
      开进程 10s (进程可以并行 同时运行4个 进程同时计算)
      开线程 40s (需要计算4次的时间才能计算完)

  四个任务 IO密集型的
    单核情况下
      开线程更节省资源(都要等 所有线程节省资源)
    多核情况下
      开线程更节省资源(即使进程可以并行 但是也需要等  而 线程 可以并发 相差不大 所以使用 线程节省资源)

from threading import Thread
import time

n = 100

def task():
    global n
    tmp = n
    time.sleep(1) #相当释放了锁 release
    n = tmp -1

t_list = []
for i in range(100):
    t = Thread(target=task)
    t.start()
    t_list.append(t)

for t in t_list:
    t.join()

print(n)

 死锁

扫描二维码关注公众号,回复: 7023284 查看本文章

RLock   (from threading import Thread,Lock,RLock)  又叫递归锁

Rlock可以被第一个抢到锁的人连续的acquire和release
每acquire一次锁身上的计数加1
每release一次锁身上的计数减1
只要锁的计数不为0 其他人都不能抢

from threading import RLock,Thread

mutex = RLock()

class MyThread(Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        mutex.acquire()
        print('{}抢到了锁'.format(self.name))
        mutex.acquire()
        print('{}抢到了锁'.format(self.name))
        mutex.acquire()
        print('{}抢到了锁'.format(self.name))
        mutex.acquire()
        print('{}抢到了锁'.format(self.name))
        
        mutex.release()
        print('{}释放了锁'.format(self.name))
        mutex.release()
        print('{}释放了锁'.format(self.name))
        mutex.release()
        print('{}释放了锁'.format(self.name))
        mutex.release()
        print('{}释放了锁'.format(self.name))

if __name__ == '__main__':
    for i in range(10):
        t = MyThread(i)
        t.start()
递归锁

信号量 (信号量可能在不同的领域中 对应不同的知识点  例如Django)

互斥锁:一个厕所(一个坑位)

信号量:公共厕所(多个坑位)

from threading import Semaphore,Thread
import time
import random


sm = Semaphore(5)  # 造了一个含有五个的坑位的公共厕所  使用方法和 LOCK一样 生成对象

def task(name):
    sm.acquire()
    print('%s占了一个坑位'%name)
    time.sleep(random.randint(1,3))
    sm.release()

for i in range(40):
    t = Thread(target=task,args=(i,))
    t.start()

抢到锁的人执行完后走了 马上就会有人来了

event事件

方法 : set wait Event

生成对象 e = Event

复习 queue模块 

同一个进程下的多个线程本来就是数据共享 为什么还要用队列
因为队列是管道+锁 使用队列你就不需要自己手动操作锁的问题
因为锁操作的不好极容易产生死锁现象

q = queue.Queue() 方法  put get  取完原地等待

q = queue.LifoQueue()  last in fast out 后进 先出  

q = queue.PriorityQueue()  put() 里面放的是元组   数字越小 优先级越高  例如 (-5, '哈哈哈')

猜你喜欢

转载自www.cnblogs.com/lddragon/p/11354368.html