Python进阶基础学习(多线程)

Python进阶学习笔记(一)

 

threading模块

threading.thread(target = (函数))  负责定义子线程对象

threading.enumerate()  负责查看子线程对象

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import time
import threading
def sing():
    for i in range(5):
        print('-----唱歌-----')
        time.sleep(1)
 
def dance():
    for i in range(5):
        print('-----跳舞-----')
        time.sleep(1)
 
def main():
    t1 = threading.Thread(target=sing)  #子线程1
    t2 = threading.Thread(target=dance) #子线程2
    t1.start()
    t2.start()
    while True:
        print(threading.enumerate())
        if  len(threading.enumerate()) == 1:
            break
        time.sleep(1)
if __name__ == '__main__':
    main()

 

补充:

线程的调度是随机的,主线程如果在子线程之前GG,你们子线程也GG

threading.thread()不会创建线程,只有调用其实例.start()之后才会创建线程

 

通过类来创建线程

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import threading
import time
class Person(threading.Thread):
    def run(self) -> None:
        for i in range(3):
            print('aaa' + self.name)
            time.sleep(1)
 
if __name__ == '__main__':
    p = Person()
    p.start()
    for i in range(3):
        print('bbb')
        time.sleep(1)

补充:

threading.thread是一个类,通过继承并且override run函数,即可声明进程

 

多线程共享全局变量

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import threading
import time
num = 100
def test1():
    global num
    num += 1
    print(num)
def test2():
    print(num)
def main():
    t1 = threading.Thread(target=test1)
    t2 = threading.Thread(target=test2)
    t1.start()
    time.sleep(1)
    test2()
if __name__ == '__main__':
    main()

 

 

若创建线程是需要带参数,则是用args

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
num = [1,1,2,3]
 
def test1(args):
    args.append('hhs')
    print(args)
 
def main():
    t1 = threading.Thread(target=test1,args=(num,))
    t1.start()
    print(num)
 
if __name__ == '__main__':
    main()

 

补充:args后边传的是一个元组,少了逗号会报错

 

多线程共享全局变量出现的问题

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import threading
import time
 
g_num = 0
def count1(n):
    global g_num
    for i in range(n):
        g_num += 1
 
def count2(n):
    global g_num
    for i in range(n):
        g_num += 1
 
def main():
    t1 =threading.Thread(target=count1,args=(100000,))
    t2 = threading.Thread(target=count2, args=(100000,))
    t1.start()
    t2.start()
    time.sleep(2)
    print('正常num为200000,实际num为%d' % g_num)
 
if __name__ == '__main__':
    main()

 

补充:输出结果为:175586,与正常结果不相同

 

 

解析问题:

1.cpu是一句句执行的

2.若把g_num += 1解析成很多句,如果线程1只执行1-2句,第三句还没赋值回去,就调用了线程2,则会出现相加的结果不等于预期的结果

 

互斥锁threading.Lock()

用于解决上面共享全局变量的问题

变量名.acquire()  上锁

变量名.release()  解锁

给要执行的代码上锁,自己运行的时候别的线程无法运行

测试代码如下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import threading
import time
 
num = 0
mutex = threading.Lock()
def count1(n):
    global num
    for i in range(n):
        mutex.acquire()
        num += 1
        mutex.release()
 
def count2(n):
    global num
    for i in range(n):
        mutex.acquire()
        num += 1
        mutex.release()
 
def main():
    t1 =threading.Thread(target=count1,args=(100000,))
    t2 = threading.Thread(target=count2, args=(100000,))
    t1.start()
    t2.start()
    time.sleep(2)
    print('正常num为200000,实际num为%d' % num)
 
if __name__ == '__main__':
    main()

 

  

 

 

posted @   SiNanhong  阅读(318)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示