初识多线程

Posted gouq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识多线程相关的知识,希望对你有一定的参考价值。

 1 import threading
 2 import time
 3 def coding():
 4     for i in range(3):
 5         print(输入代码%s %i)
 6         time.sleep(1)
 7 def drawing():
 8     for i in range(3):
 9         print(开始画画%s%i)
10         time.sleep(1)
11 def main():
12     t1 = threading.Thread(target=coding)
13     t2 = threading.Thread(target=drawing)
14 
15     t1.start()
16     t2.start()
17 if __name__ == __main__:
18     main()
19 
20 Output:
21 
22 D:PyCharmAnaconda3python.exe D:/PyCharm/Py_work/test2.py
23 输入代码0
24 开始画画0
25 输入代码1
26 开始画画1
27 输入代码2
28 开始画画2
29 
30 Process finished with exit code 0

还可以通过继承Thread类来创建多线程:

 1 import threading
 2 import time
 3 class codingThread(threading.Thread):
 4     def run(self):
 5         for i in range(3):
 6             print(输入代码%s %threading.current_thread())
 7             time.sleep(1)
 8 class drawingThread(threading.Thread):
 9     def run(self):
10         for i in range(3):
11             print(开始画画%s%threading.current_thread())
12             time.sleep(1)
13 def main():
14     t1 = codingThread()
15     t2 = drawingThread()
16 
17     t1.start()
18     t2.start()
19 if __name__ == __main__:
20     main()
21 
22 Output
23 
24 D:PyCharmAnaconda3python.exe D:/PyCharm/Py_work/test2.py
25 输入代码<codingThread(Thread-1, started 8836)>
26 开始画画<drawingThread(Thread-2, started 9080)>
27 开始画画<drawingThread(Thread-2, started 9080)>
28 输入代码<codingThread(Thread-1, started 8836)>
29 输入代码<codingThread(Thread-1, started 8836)>
30 开始画画<drawingThread(Thread-2, started 9080)>
31 
32 Process finished with exit code 0

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

多线程都是在同一个进程中运行的。因此在进程中的全局变量所有线程都是共享的。这就造成了一个问题,因为线程执行的顺序是无序的,有可能会造成数据错误。

 1 ###当数据量小的时候,可能不会出错,如下:
 2 import threading
 3 value = 0
 4 def add_value():
 5     global value
 6     for i in range(1000):
 7         value += 1
 8     print(value)
 9 def main():
10     for x in range(2):
11         t = threading.Thread(target=add_value)
12         t.start()
13 
14 if __name__ == __main__:
15     main()
16 
17 Output
18 
19 1000
20 2000

第一个线程先加到1000,第二线程再加到2000,这里看起来没什么问题。但是当数据量大的时候,问题就出现了,如下:

 1 import threading
 2 value = 0
 3 def add_value():
 4     global value
 5     for i in range(1000000):
 6         value += 1
 7     print(value)
 8 def main():
 9     for x in range(2):
10         t = threading.Thread(target=add_value)
11         t.start()
12 
13 if __name__ == __main__:
14     main()
15 
16 Output
17 
18 1222047
19 1246006

按理说应该先输出1000000,再输出2000000。但是结果却不是,这就是多线程执行顺序无序的后果。举个例子:当value=10的时候,线程1和线程2同时启动,本来value经过两个线程执行后应该是value=12。但是由于两个线程是同时执行,导致value +=1 被同时执行了两次,最后的结果就是value还是等于11.

这时候,就需要一个来消除这种不好的后果。就是如果线程1比线程2线对value先执行的时候,那么就先把value给锁起来,不让其他线程对value进行任何操作,等线程1操作完后再对value 进行解锁,这时候其他线程才可以对value进行操作。(这样看起来,好像和单线程没啥区别~~~~~)。

注意:这个锁一般只用于多个线程修改全局变量的代码段。比如下面代码的7行和8行。

 1 import threading
 2 value = 0
 3 gLock = threading.Lock()
 4 def add_value():
 5     global value
 6     gLock.acquire()  #上锁
 7     for i in range(1000000):
 8         value += 1
 9     gLock.release()  #解锁
10     print(value)
11 def main():
12     for x in range(2):
13         t = threading.Thread(target=add_value)
14         t.start()
15 
16 if __name__ == __main__:
17     main()
18 
19 Output
20 
21 1000000
22 2000000

 

 

Lock版本生产者和消费者模式

生产者和消费者模式是多线程开发中经常见到的一种模式。生产者的线程专门用来生产一些数据,然后存放到一个中间变量中。消费者再从这个中间的变量中取出来数据进行消费。但是因为要使用中间变量,中间变量经常是一些全局变量,因此余姚使用锁来保证数据完整性。

 1 import threading,random,time
 2 
 3 gMoney = 1000 #此全局变量用来保存生产和消费的钱
 4 gLock = threading.Lock()
 5 gTotalTimes = 10  #此全局变量用来保存需要消费多少次
 6 gtimes = 0   #此全局变量用来保存生产了多少次
 7 
 8 class producer(threading.Thread):  #生产者
 9     def run(self):
10         global gMoney,gtimes
11         while True:
12             money = random.randint(100,1000)
13             gLock.acquire()     #上锁
14             if gtimes >= gTotalTimes:  #如果生产了10次,就退出循环
15                 gLock.release()
16                 break
17             gMoney += money
18             print(%s生产了%d元钱,剩余%d元钱 %(threading.current_thread(),money,gMoney))
19             gtimes += 1
20             gLock.release()    #解锁
21             time.sleep(0.5)
22 
23 class consumer(threading.Thread):  #消费者
24     def run(self):
25         global gMoney
26         while True:
27             money = random.randint(100,1000)
28             gLock.acquire()
29             if gMoney >= money:
30                 gMoney -= money
31                 print(%s消费了%d元钱,剩余%d元钱 % (threading.current_thread(), money, gMoney))
32             else:
33                 if gtimes >= gTotalTimes:
34                     gLock.release()
35                     break
36                 print(%s消费者准备消费%d元钱,剩余%d元钱,余额不足 % (threading.current_thread(), money, gMoney))
37 
38             gLock.release()  #此处的解锁如果放在if代码块里面,可能会造成死锁
39             time.sleep(0.5)
40 
41 def main():
42     for i in range(5):
43         t = consumer(name=消费者线程%d %i)
44         t.start()
45 
46     for i in range(5):
47         t = producer(name=生产者线程%d %i)
48         t.start()
49 
50 if __name__ == __main__:
51     main()

 

以上是关于初识多线程的主要内容,如果未能解决你的问题,请参考以下文章

初识多线程之基础知识与常用方法

初识多线程

初识多线程

进程线程区别,和线程初识

多线程 Thread 线程同步 synchronized

Java核心知识---初识线程