版权声明:拥抱开源,欢迎转载,转载请保留原文链接~ https://blog.csdn.net/u010429424/article/details/76100149 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
<div id="content_views" class="markdown_views">
<!-- flowchart 箭头图标 勿删 -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg>
<h2 id="python多线程小例子"><a name="t0"></a>Python多线程小例子</h2>
1、在主线程中创建子线程
下面的代码一共创建了三个线程:主线程、coding 线程和music 线程,最后使用thread_list 装载线程
from time import ctime
import threading
def coding(language):
for i in range(5):
print('I\'m coding ',language, ' program at ', ctime() )
def music():
for i in range(5):
print('I\'m listening music at ', ctime())
if __name__ == '__main__':
print('thread %s is running...' % threading.current_thread().name)
thread_list = []
t1 = threading.Thread(target=coding, args=('Python',))
t2 = threading.Thread(target=music)
thread_list.append(t1)
thread_list.append(t2)
for t in thread_list:
t.setDaemon(True) # 设置为守护线程
t.start()
t.join() # 在这个子线程完成运行之前,主线程将一直被阻塞
print('thread %s ended.' % threading.current_thread().name)
- 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
运行效果如下:
t.join()的作用是:在子线程完成运行前,主线程将处于阻塞的状态,否则主线程会一直运行,并且主线程运行结束后,子线程也一同结束。
如果我们把join去掉,则运行结果可能为:
2、lock 锁
在多线程中,变量由各个线程共享,对共享变量,需要加锁。
举一个最常见的例子:我们经常在银行存钱、取款,其中一个线程负责存钱,另一个线程负责取款。如果不加控制,很容易就把钱数算错了。我们看看银行是怎么算错钱数的:
import threading
money = 0 # 变量 money 被 t1和 t2 两个线程共享
# 存钱
def put_money(sum):
global money
money += sum
# 取钱
def get_money(sum):
global money
money -= sum
def run_thread(sum):
for i in range(1000000): #执行的次数要足够多
# 先存sum,后取sum,钱数应当为0
put_money(sum)
get_money(sum)
t1 = threading.Thread(target=run_thread, args=(100,))
t2 = threading.Thread(target=run_thread, args=(1000,))
t1.start()
t2.start()
t1.join()
t2.join()
print(money)
- 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
在上面的例子中,我们先存sum元钱,再取sum元钱,总钱数应当一直为0。这在单线程中没有问题。
然而在多线程中,操作系统交叉执行赋值语句,导致全局变量被一个线程修改了,另一个线程却不知情的情况。
因为在操作系统中,money += sum,是被拆成两条语句执行的:
x = money + sum
money = x
这两条语句的执行顺序 很可能是乱序的,我们看看下面的表格就理解了,最后你会惊奇地发现 少了5元钱!:-(
实际结果也验证了这一问题:
哈哈哈,我们居然多出了2900元。很显然,银行家们肯定不能允许这种情况发生,所以,他们也在学习如何使用lock :-)
可以通过lock解决这个问题:
def run_thread(sum):
for i in range(1000000):
lock.acquire() # 改动1...........加锁
try:
put_money(sum)
get_money(sum)
finally:
lock.release() # 改动2......别忘了释放锁:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
“当多个线程同时执行lock.acquire()时,只有一个线程能成功地获取锁,然后继续执行代码,其他线程就继续等待直到获得锁为止。”————引用自多线程-廖雪峰的官方网站
其实和上厕所一个道理,一个人蹲坑,另一个人只能等着 :-)
这下好了,银行家们在 run_thread 方法中添加了lock,这次程序运行的结果如下,我们看到钱数始终为0:
除了多线程外,Python 多进程也经常使用,参见:
http://blog.csdn.net/u010429424/article/details/76147368
参考:
http://www.cnblogs.com/fnng/p/3670789.html
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143192823818768cd506abbc94eb5916192364506fa5d000
See u ~