1.线程安全
首先我们知道线程是共享资源的,在这个基础上我们提出一个问题,如果我们有一个变量a = 0
然后10个线程都是给它+1的 然后我们执行这个10个线程,最后a = 10吗?
我们先看下面的代码
1 __author__ = 'Rico' 2 #_*_coding:utf-8_*_ 3 from threading import Thread 4 a = 0 5 class Plusone(Thread): 6 def __init__(self): 7 super(Plusone,self).__init__() 8 def run(self): 9 global a 10 a += 1 11 12 for i in range(30): 13 temp = Plusone() 14 temp.start() 15 16 print a
如果没错的的应该输入的是30
但是---》
结果是29
当然这不是每次都会出现的,是不固定的,看电脑的配置的,和线程的个数
由此 我们知道 变量之所以没有得到我们想要的值,是因为线程之间抢占了变量,导致了问题的发生 --->结论:Python不是一个线程安全的语言
那么我们要自己保证线程安全了那么引出了下面的概念
2线程锁
我们去买衣服的时候,试衣间里面会不会出现两个人?并不会。为什么呢? 因为每个人进去之后会反锁门,走的时候才打开。这就是线程锁的概念
我们修改下run函数
1 def run(self): 2 lock.acquire() 3 global a 4 a += 1 5 print a 6 lock.release()
lock.acquire()#在执行这个时候,线程会独占cpu
lock.release()#释放
在执行两个操作的时候之间其实就是单线程了
Python有一个叫全局解释器锁的东西我们大家都知道--进行cpu操作的时候,因为全局解释器锁的原因
你起了一个多线程,其实还是一个单线程,其他的线程其实都在切片
1 __author__ = 'Rico' 2 #_*_coding:utf-8_*_ 3 from threading import Thread,Lock 4 import time 5 a = 0 6 class Plusone(Thread): 7 def __init__(self,name): 8 self.__name = name 9 super(Plusone,self).__init__() 10 def run(self): 11 global a 12 lock.acquire() 13 a += 1 14 lock.release() 15 print "%s " % a 16 lock =Lock() 17 18 for i in range(200): 19 temp = Plusone(i) 20 temp.start() 21 22 print a
我们在跑这个代码的时候,就可以感受到了 无论你开多少线程 最后还是顺序的切片 但是如果你把run函数变成这样
def run(self): global a lock.acquire() a += 1 lock.release() time.sleep(1) print "%s " % a
cpu默认都之拿来100条指令 当加入了sleep(1) 就不等了 直接切了
3信号量 同时允许及格线程访问同一个数据
1 __author__ = 'Rico' 2 #_*_coding:utf-8_*_ 3 from threading import Thread,Lock,BoundedSemaphore 4 import time 5 a = 0 6 class Plusone(Thread): 7 def __init__(self,name): 8 self.__name = name 9 super(Plusone,self).__init__() 10 def run(self): 11 time.sleep(1) 12 global a 13 samp.acquire() 14 a += 1 15 print "%s" % a 16 samp.release() 17 samp = BoundedSemaphore(10) 18 for i in range(200): 19 temp = Plusone(i) 20 temp.start() 21 22 print a