学习Python的日子 Python高级(7)

Python高级
互斥锁
from threading import Thread, Lock
 suo=Lock()
 f=suo.acquire() #  获取锁    锁门


 suo.acquire()
 print("-----",f)


 suo.release()  # 开门   释放锁
案例
from threading import Thread


# 全局变量
g_num = 0




# def worker1():
# global g_num
# # 请求获取锁
# l.acquire()
# for i in range(1000000):
# g_num += 1
# # 释放锁
# l.release()
# print("在worker1中g_num==", g_num)
#
#
# def worker2():
# global g_num
# # 请求获取锁
# l.acquire()
#
# for i in range(1000000):
# g_num += 1
#
# # 释放锁
# l.release()
# print("在worker2中g_num==", g_num)
优化
def worker1():
global g_num


for i in range(1000000):
# 请求获取锁
l.acquire()
g_num += 1
# 释放锁
l.release()
print("在worker1中g_num==", g_num)




def worker2():
global g_num


for i in range(1000000):
# 请求获取锁
l.acquire()
g_num += 1
# 释放锁
l.release()
print("在worker2中g_num==", g_num)




if __name__ == "__main__":
# 1. 创建一把锁
l = Lock()
t1 = Thread(target=worker1)


t2 = Thread(target=worker2)


t1.start()


t2.start()


t1.join()
t2.join()


print("---主-->", g_num)
死锁(避免死锁)
锁: 只要获取了锁,但是如果不释放,再次获取的时候就会阻塞
程序中使用多个锁,A,B锁,使用锁的顺序不当
Thread1:  先获取A,sleep(0.01) 就要获取B锁, 工作  释放B,A锁
Thread2:  先获取B,sleep(0.01) 就要获取A锁, 工作  释放B,A锁
原因
1.使用了多个锁
2.使用顺序不当
解决方式
f=l.acquire(timeout=1)   # 设置acquire的超时时间  如果达到时间则会直接返回False,就不会继续阻塞
案例
from threading import Thread, Lock
from time import sleep


s1 = Lock()  # A
s2 = Lock()  # B




class Thread1(Thread):
def run(self):
if s1.acquire():
print(self.name, "获取锁A,即将获取锁B")
sleep(0.01)
if s2.acquire(timeout=1):
print(self.name, "获取A和B锁!")
s2.release()
s1.release()




class Thread2(Thread):
def run(self):
if s2.acquire():
print(self.name, "获取锁B,即将获取锁A")
sleep(0.01)
if s1.acquire(timeout=1):
print(self.name, "获取A和B锁!")
s1.release()
s2.release()




if __name__ == "__main__":
# 创建线程对象


Thread1().start()
Thread2().start()


threading
线程安全
全局变量
GIL  全局解释器锁   ----》python
10个线程  ----》GIL
python 2  --->1000字节码
python 3 ---》15毫秒
GIL: 4  8  2  1核心
优点
计算密集型:CPU   ---》不希望GIL  消耗cpu资源
IO密集型:GIL
在哪个线程的x获取的就是哪个线程的值
子线程中不能访问主线程的值
多线程应用
from threading import Thread, Lock
from time import sleep




def print_lower():
for i in [chr(x) for x in range(ord('a'),ord('z')+1)]:
if s1.acquire():
print(i)
s2.release()




def print_upper():
for i in [chr(x) for x in range(ord('A'),ord('Z')+1)]:
if s2.acquire():
print(i)
s1.release()




if __name__ == "__main__":
# 3把锁
s1 = Lock()
s2 = Lock()
s1.acquire()




t1 = Thread(target=print_lower, name="小写字母")


t2 = Thread(target=print_upper, name="大写字母")


t1.start()
t2.start()
生产者与消费者
生产者与消费者模式: 其实就是指线程间通信
案例
from threading import Thread
from queue import Queue
from time import sleep


count = 500




# 1. 准备两个线程类


class Producer(Thread):
def run(self):
global count
while True:
if q.qsize() < 500:
for i in range(1, 6):
count += 1
msg = "烤鸭-%d" % count
q.put(msg)
print(self.name,"生产了:", msg)
sleep(0.6)




class Consumer(Thread):
def run(self):
while True:
if q.qsize() > 200:
for i in range(50):
msg = q.get()
print(self.name,"消费了:%s" % msg)
sleep(0.6)




if __name__ == "__main__":
q = Queue()


# 造面包
for i in range(1, 501):
q.put("烤鸭-%d" % i)


# 生产者


Producer().start()


# 消费者


Consumer().start()


socket
发送端   ---  接收端
客户端   ---  服务端
socket 通信的桥梁
UDP
无连接的传输协议   视频  视频会议  现场直播     没有三次握手
     没有校验
     socket.SOCK_DGRAM
     QQ
TCP
socket.SOCK_STREAM  三次握手
socket.AF_INET, 不同电脑
socket.AF_UNIX  同一个电脑
网络编程发送
步骤
1、创建客户端套接字
2、发送/接收数据
3、关闭套接字
案例
send_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
send_socket.bind(("",9992))
# print(send_socket)
# sendto(发送的内容,接收方)  内容必须编码   接收方:元组  (接收方IP,接收方的端口号)
while True:
msg = input("请输入:")
send_socket.sendto(msg.encode("utf-8"), ("192.168.28.47", 9991))
if msg == "bye":
break
# 接收信息
content = send_socket.recvfrom(512)  # 阻塞
print("收到消息:",content[0].decode("utf-8"))
# print(content[1])


send_socket.close()
网络编程接收
1、创建客户端套接字
2、发送/接收数据
3、关闭套接字
接收方
from socket import *


recv_socket = socket(AF_INET, SOCK_DGRAM)


# 绑定端口号  设定字节的端口号
recv_socket.bind(("", 9991))


while True:
# 接收信息
content = recv_socket.recvfrom(1024)  # 阻塞方法
msg = content[0].decode("utf-8")
print("收到消息:",msg)
# coutent[1] (IP,port)  发送方的ip,port
# print("IP:", content[1][0])
# print("port:", content[1][1])
if msg == "bye":
break


# 回复信息
msg = input("请输入:")
recv_socket.sendto(msg.encode("utf-8"), content[1])


recv_socket.close()
步骤
1.创建socket对象
from socket import *

s=socket(AF_INET,SOCK_DGRAM)
2. 给自己设置端口号
s.bind(("",port))
3. 发送或者接收消息:
发送: s.sendto(内容,目的地)  目的地(ip,port)
接收:  s.recvfrom(1024)  1024是指缓存的大小   返回值就是接到的内容 
内容也是一个元组,(内容,发送方法的信息)  发送方信息(ip,port)
4. 关闭socket
总结
Process:
1.自定义进程
2.进程池 Pool
obj=pool.apply(task,args=(...))   obj 就是task函数的返回值   阻塞
obj=pool.apply_async(task,args=(..),callback=函数)        非阻塞
3.进程间通信:
Queue ---》put("aa")  put(5)  put()  |   get(timeout=1) 阻塞
put_nowait()   |  get_nowait()
qsize()  full()  empty()


Process + Queue
pool  + Manager().Queue()


线程:
Thread


from threading import Thread


1. 类似  Thread(target=task,args=(...))    t.start()   t.join()
2. 自定义线程
3. Thread: A. 全局就是共享数据   B.局部中的数据就是非共享
4. 共享数据的安全问题:
A.多个线程访问的是共享数据
B.操作共享数据的代码是由多行代码组成


num +=1  --->  num=num+1

猜你喜欢

转载自blog.csdn.net/qq_42240071/article/details/80447727
今日推荐