多任务
一、同步异步概念
- 同步就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。
- 进程、线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行;B依言执行,再将结果给A;A再继续操作。
- 同步调用就是你喊你朋友吃饭,你朋友再忙,你就一直在那等,等你朋友忙完了,你们一起去。
- 异步调用就是你喊你朋友吃饭,你朋友说知道了,待会忙完去找你,你就去做别的了。
二、互斥锁
- 当多个线程几乎同时修改一个共享数据的时候,需要进行同步控制,线程同步能够保证多个线程安全的访问竞争资源(全局内容),最简单的同步机制就是使用互斥锁。
- 某个线程要更改共享数据时,先将其锁定,此时资源的状态是锁定状态,其他线程就不能更改,知道该线程将资源状态改为非锁定状态,也就是释放资源,其他的线程才能再次锁定资源。互斥锁保证了每一次只有一个线程进入写入操作。从而保证了多线程下数据的安全性。
- threading模块中定义了Lock类,可以方便的处理锁定:
- 创建锁:
mutex=threading.Lock() - 锁定
mutex.acquire() - 释放
mutex.release()
- 创建锁:
from threading import Thread,Lock
g=0
def hs1():
global g
for i in range(100000):
l.acquire()
g+=1
l.release()
print("函数1",g)
def hs2():
global g
for i in range(100000):
l.acquire()
g+=1
l.release()
print("函数2",g)
if __name__ == '__main__':
l=Lock()
t1=Thread(target=hs1)
t2=Thread(target=hs2)
t1.start()
t2.start()
三、死锁
from threading import Thread,Lock
import time
g=0
def hs1():
global g
for i in range(100000):
l1.acquire()
print("函数1锁1得到锁,请求锁2")
# time.sleep(1)
l2.acquire()
print("11111111111111")
g+=1
l2.release()
l1.release()
print("函数1",g)
def hs2():
global g
for i in range(100000):
l2.acquire()
print("函数2锁1得到锁,请求锁2")
l1.acquire()
print("222222222222")
g+=1
l1.release()
l2.release()
print("函数2",g)
if __name__ == '__main__':
l1=Lock()
l2=Lock()
t1=Thread(target=hs1)
t2=Thread(target=hs2)
t1.start()
t2.start()
四、生产者和消费者
- python的queue模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。
from threading import Thread
import queue,time
def produce(q,name):
count=1
while True:
bz=name+"蒸的包子%d"%count
q.put(bz)
print(bz)
count+=1
time.sleep(1)
def consum(q,name):
while True:
bz=q.get()
print(name,"吃",bz)
time.sleep(1)
if __name__ == '__main__':
q=queue.Queue(5)
t1=Thread(target=produce,args=(q,"张三"))
t2=Thread(target=produce,args=(q,"李四"))
t3=Thread(target=consum,args=(q,"王五"))
t4=Thread(target=consum,args=(q,"赵六"))
t5=Thread(target=consum,args=(q,"我"))
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
五、threadLocal
一个threadLocal变量虽然是全局变量,但每个线程都只能读写自己线程的独立副本,互不干扰。threadLocal解决了参数在一个线程中各个函数之间互相传递的问题。
from threading import Thread
import threading,time
local=threading.local()
def hanshu1(name):
local.name=name
hanshu2()
def hanshu2():
print(threading.current_thread(),local.name)
if __name__ == '__main__':
t1=Thread(target=hanshu1,args=("张三",),name="线程帅哥")
t2=Thread(target=hanshu1,args=("李四",),name="线程美女")
t1.start()
t2.start()
六、协程
在一个函数中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者确定。
def hanshu():
for i in range(3):
print("函数1",i)
yield
def hanshu2(a):
for i in range(3):
next(a)
print("函数2",i)
h=hanshu()
hanshu2(h)
网络编程
osi七层模型
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
TCP协议
UDP协议
- UDP协议:面向无连接,数据不安全,速度快。不区分客户端与服务器。
socket
import threading
from socket import *
udp_s=socket(AF_INET,SOCK_DGRAM)
dest_address=(IP地址,9123) # 对方的IP地址,字符串格式
udp_s.bind((IP地址,9124)) # 自己的IP地址,字符串格式
def send():
while True:
data = input()
udp_s.sendto(data.encode("utf-8"), dest_address)
def receive(name):
while True:
s=udp_s.recvfrom(1024)
print()
print(name+":",s[0].decode("utf-8"))
if __name__ == '__main__':
t1=threading.Thread(target=send)
t2=threading.Thread(target=receive,args=("张三",))
t1.start()
t2.start()