Python多线程实例 pymysql.err.InternalError: Packet sequence number wrong - got 45 expected 0

前言

  感觉理解python多线程用“切换”和“共享”就差不多了。这里就贴上一个抢车票的小小实例,还有自己在编程过程中遇到的坑.....

实例:抢车票

抢车票有三类人:会员、弄了加速包、普通人。

说说区别:

  钱带来的不公平:会员先跑,然后加速包,最后普通人

  可以欣慰的公平:跑道一样长

守护线程SetDaemon

不设置守护进程

 1 import threading
 2 import time
 3 #使用函数式
 4 
 5 #会员
 6 def vip(t1):
 7     global num
 8     time.sleep(2)   #等待时间相同,区别是进场的先后顺寻
 9     if num == 15:
10         print("用时:", time.time() - t1)
11         exit(0)
12     num += 1
13     print('会员,当前被抢票数:', num)
14 #有加速包的家伙
15 def aboostOne(t1):
16     global num
17     time.sleep(2)       #等待时间相同,区别是进场的先后顺寻
18     if num == 15:
19         print("用时:",time.time()-t1)
20         exit(0)
21     num+=1
22     print('加速包,当前被抢票数:', num)
23 
24 #没有加速包的苦逼
25 def commonOne(t1):
26     global num
27     time.sleep(2)   #等待时间相同,区别是进场的先后顺寻
28     if num == 15:
29         print("用时:", time.time() - t1)
30         exit(0)
31     num += 1
32     print('苦逼青年,当前被抢票数:', num)
33 
34 if __name__ =='__main__':
35     t1 =time.time()     #开始时间
36     num =0  #只有15张票
37     #vip优先,来3个
38     for i in range(3):
39         threading.Thread(target=vip,args=(t1,)).start()
40     #加速包其次,来7个
41     for i in range(7):
42         threading.Thread(target=aboostOne,args=(t1,)).start()
43     #苦逼青年最后,来10个
44     for i in range(10):
45         threading.Thread(target=commonOne,args=(t1,)).start()
exam1

结论:

  1.加速包可以抢的比会员卡   ===   多线程不一定按顺序进行

  2.最终打出了5个用时 ===  一个线程exit()之后,其他线程不受影响,继续运行

再看看设置守护

其他代码不变,只给苦逼青年daemon.图中有两种方式

结果:

  苦逼青年抢票被中断,抛出异常  ===  设置守护意味着不重要,主线程退出,守护进程随即被中断

  

join()设置阻塞

 在setDaemon的情况下join,只测试苦逼青年的

 结果:

  完美运行完了 === join的作用:被join的子线程执行完之后,主线程才能进行。

  这里就算SetDaemon,主线程也带等苦逼青年运行完。SetDaemon后,用join,相当于没有设置守护进程

  作用:当你想做完一些事,再做另一些事,就可以join一下

 遇到的坑

pymysql.err.InternalError: Packet sequence number wrong - got 45 expected 0

原因:

使用了多线程,多线程共享了同一个数据库连接,但每个execute前没有加上互斥锁

方法:

方法一:每个execute前加上互斥锁

        lock.acquire()
        cursor.execute(command,data)     
        lock.release()

方法二:

  每个线程拥有自己的数据库连接,即在线程调用函数中加上数据库连接代码

方法三:

       所有线程共用一个连接池,需要考虑线程总数和连接池连接数上限的问题     

另外

threading.Thread(target =,args=(,))

  args应当传入Tuble(元组)

  第二:传入的参数不是引用传递,而是新分配了内存。估计是把参数初始化到类的成员里面去了吧

转自:https://www.cnblogs.com/heiao10duan/p/9373237.html

猜你喜欢

转载自www.cnblogs.com/vvlj/p/10674003.html