多线程

一多线程的创建(t利用hreading模块)

import threading
import time
def loop_thread():
    print '%s is running ' % threading.current_thread().name
    print '%s is end' % threading.current_thread().name

print '%s is running' % threading.current_thread().name
for i in range(5):
    t = threading.Thread(target=loop_thread)
    t.start()
    t.join()
print '%s is end' % threading.current_thread().name

结果如图:


二线程锁Lock

多线程和多进程最大的不同在于多进程中,对于同一个变量,每个进程都会拷贝一份到自己的进程里面操作。不会相互影响。而多线程中,多线程共享所有变量,如果多线程同时修改一个变量,可能导致结果错乱。

例如:

import threading
balance = 0
def run_thread(n):
    for i in range(1000):
        change(n)
def change(n):
    global balance
    balance +=n
    balance -=n
    

if __name__=='__main__':
    print '%s is running' % threading.current_thread().name
    t1 = threading.Thread(target=run_thread,args=(8,))
    t2 = threading.Thread(target=run_thread,args=(5,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print '%s is end' % threading.current_thread().name
    print balance

运行3次的结果:

每次都不一样。。。。结果错乱了。


我们定义了一个共享变量balance,初始值为0,并且启动两个线程,先存后取,理论上结果应该为0,但是,由于线程的调度是由操作系统决定的,当t1、t2交替执行时,只要循环次数足够多,balance的结果就不一定是0了。

原因是因为高级语言的一条语句在CPU执行时是若干条语句,即使一个简单的计算:

balance = balance + n
也分两步:


计算balance + n,存入临时变量中;
将临时变量的值赋给balance。
也就是可以看成:

x = balance + n
balance = x
由于x是局部变量,两个线程各自都有自己的x,当代码正常执行时:
初始值 balance = 0


t1: x1 = balance + 5 # x1 = 0 + 5 = 5
t1: balance = x1     # balance = 5
t1: x1 = balance - 5 # x1 = 5 - 5 = 0
t1: balance = x1     # balance = 0


t2: x2 = balance + 8 # x2 = 0 + 8 = 8
t2: balance = x2     # balance = 8
t2: x2 = balance - 8 # x2 = 8 - 8 = 0
t2: balance = x2     # balance = 0


结果 balance = 0
但是t1和t2是交替运行的,如果操作系统以下面的顺序执行t1、t2:


初始值 balance = 0


t1: x1 = balance + 5  # x1 = 0 + 5 = 5


t2: x2 = balance + 8  # x2 = 0 + 8 = 8
t2: balance = x2      # balance = 8


t1: balance = x1      # balance = 5
t1: x1 = balance - 5  # x1 = 5 - 5 = 0
t1: balance = x1      # balance = 0


t2: x2 = balance - 5  # x2 = 0 - 5 = -5
t2: balance = x2      # balance = -5


结果 balance = -5
究其原因,是因为修改balance需要多条语句,而执行这几条语句时,线程可能中断,从而导致多个线程把同一个对象的内容改乱了。


两个线程同时一存一取,就可能导致余额不对,你肯定不希望你的银行存款莫名其妙地变成了负数,所以,我们必须确保一个线程在修改balance的时候,别的线程一定不能改。


如果我们要确保balance计算正确,就要给change()上一把锁,当某个线程开始执行change()时,我们说,该线程因为获得了锁,因此其他线程不能同时执行change(),只能等待,直到锁被释放后,获得该锁以后才能改。由于锁只有一个,无论多少线程,同一时刻最多只有一个线程持有该锁,所以,不会造成修改的冲突。创建一个锁就是通过threading.Lock()来实现


import threading
lock = threading.Lock()
balance = 0
def run_thread(n):
    for i in range(1000):
        lock.acquire()
        try:
            change(n)
        finally:
            lock.release()
def change(n):
    global balance
    balance +=n
    balance -=n
    

if __name__=='__main__':
    print '%s is running' % threading.current_thread().name
    t1 = threading.Thread(target=run_thread,args=(8,))
    t2 = threading.Thread(target=run_thread,args=(5,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print '%s is end' % threading.current_thread().name
    print balance

运行三次的结果都一样是0




三额外扩展:

Python解释器由于设计时有GIL全局锁,导致了多线程无法利用多核。多线程的并发在Python中就是一个美丽的梦。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值