线程执行的顺序是不确定,可以通过适当的延时,保证某一线程先执行
基础语法
# 多线程的使用方式
import threading
def test1():...
# 如果创建Thread时执行的函数,运行结束,那么意味着,这个子线程结束了
def test2():...
def main():
t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
t1.start()
t2.start()
print(threading.enumerate())
if __name__ == '__main__':
main()
比较复杂的过程,通过类继承Thread类完成创建线程
import threading
import time
class MyThread(threading.Thread):
def fun(self):
for i in range(5):
time.sleep(1)
print("[%s]" % i)
if __name__ == '__main__':
t = MyThread()
t.start()
# start() 调用 self.run() , 涉及调用其它方法,到run函数中调用
多线程全局变量的共享
在一个函数中对全局变量进行修改的时候,到底是否需要使用global进行说明要看是否对全局变量的执行指向进行了修改,
如果修改了执行,即让全局变量指向了一个新的地方,那么必须使用global
如果,仅仅是修改了指向的空间中的数据,此时不必使用global
# 无参
import threading
import time
g_num = 100
def test1():
global g_num
g_num += 1
print("--------in test1 g_num=%d--------" % g_num)
def test2():
print("--------in test2 g_num=%d--------" % g_num)
def main():
t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
t1.start()
time.sleep(1)
t2.start()
time.sleep(1)
print("--------in main g_num=%d--------" % g_num)
if __name__ == '__main__':
main()
# 带参
import threading
import time
g_num = 100
def test1(temp):
temp.append(33)
print("--------in test1 g_nums=%s--------" % str(temp))
def test2(temp):
print("--------in test2 g_nums=%s--------" % str(temp))
g_nums = [11,22]
def main():
# target 去哪个函数执行代码
# args 带着什么过去的
t1 = threading.Thread(target=test1, args=(g_nums,))
t2 = threading.Thread(target=test2, args=(g_nums,))
t1.start()
time.sleep(1)
t2.start()
time.sleep(1)
print("--------in main g_nums=%s--------" % str(g_nums))
if __name__ == '__main__':
main()
多线程任务的资源竞争
import threading
import time
g_num = 0
def test1(num):
global g_num
for i in range(num):
g_num += 1
print("----in test1 g_num=%d----" % g_num)
def test2(num):
global g_num
for i in range(num):
g_num += 1
print("----in test2 g_num=%d----" % g_num)
def main():
t1 = threading.Thread(target=test1, args=(1000000,))
t2 = threading.Thread(target=test2, args=(1000000,))
t1.start()
t2.start()
time.sleep(5)
print("----in main gnum=%d----" % g_num)
if __name__ == '__main__':
main()
"""
----in test1 g_num=1188472----
----in test2 g_num=1319841----
----in main g_num=1319841----
"""
互斥锁,避免资源竞争
import threading
import time
g_num = 0
def test1(num):
global g_num
# 上锁,如果之前没有被上锁,那么此时,上锁成功
# 如果上锁之前,已经被上锁了,那么此时会阻塞在这里,直到这个锁被解开为止
mutex1.acquire()
for i in range(num):
g_num += 1
mutex1.release()
print("----in test1 g_num=%d----" % g_num)
def test2(num):
global g_num
mutex1.acquire()
for i in range(num):
g_num += 1
mutex1.release()
print("----in test2 g_num=%d----" % g_num)
mutex1 = threading.Lock()
def main():
t1 = threading.Thread(target=test1, args=(1000000,))
t2 = threading.Thread(target=test2, args=(1000000,))
t1.start()
t2.start()
time.sleep(1)
print("----in main gnum=%d----" % g_num)
if __name__ == '__main__':
main()
多线程版UDP聊天器
import socket
import threading
# 接收数据
def recv_msg(udp_socket):
while True:
recv_data,data_from = udp_socket.recvfrom(1024)
print("来自%s: [%s] " % (data_from, recv_data.decode('gbk')))
# 接收数据
def send_msg(udp_socket):
while True:
send_data = input("输入要发送的数据:")
udp_socket.sendto(send_data.encode('gbk'),("192.168.2.193", 8080))
def main():
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 2. 绑定本地信息
udp_socket.bind(("", 7890))
# 对方的连接信息,用的固定值,没有用变量传递
# 创建两个线程
t_recv = threading.Thread( target=recv_msg, args=(udp_socket,))
t_send = threading.Thread( target=send_msg, args=(udp_socket,))
t_recv.start()
t_send.start()
if __name__ == '__main__':
main()