先执行 并发线程再执行 下一个主线程
#_*_coding:utf-8_*_
importthreadingimporttimedefrun(num):globalNUM
time.sleep(1)print "hi i am thread %s ...lalala" %num
NUM+= 1NUM=0
p_list=[]for i in range(30):
t= threading.Thread(target=run,args=(i,))
t.start()
p_list.append(t)#我们自己实现并行,先让并发线程执行,加到列表等待我们取结果即可
#t.jion() # 等待一个线程结束才会执行第二个线程,这样就成了串行,而不是并行了
for i in p_list: # i.join() #取出我们上面放入的结果。 但是串行取出
print '---->',NUM #由于加入列表时候是并发加入的,数字没有先后,所以打印结果i的时候也就看到没有顺序。最后打印的的i会导致 NUM的变化
View Code
既不让NUM变化又实现并发 而且还是先实现并发线程后再执行 主线程 也就是再执行print NUM
RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。 如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。
#_*_coding:utf-8_*_
import threading
import time
def run(num):
global NUM
lock.acquire() #上锁 注意位置,理论上是要 上锁 处理数据 解锁。一定要看好sleep时间
print " hi i am thread %s ...lalala " % num
NUM += 1
lock.release() #释放锁
time.sleep(1)
NUM =0
p_list = []
lock = threading.Lock() #制造一把锁
for i in range(30):
t = threading.Thread(target=run,args=(i,))
t.start()
p_list.append(t) #我们自己实现并行,先让并发线程执行,加到列表等待我们取结果即可
#t.jion() # 等待一个线程结束才会执行第二个线程,这样就成了串行,而不是并行了
for i in p_list: #
i.join() #取出我们上面放入的结果。 但是串行取出
print '---->',NUM #由于加锁了,所以会数字不会变化
信号量 semaphore 讲解: 区别一个数据一个线程即一个厕所一把钥匙 一个厕所5个坑 5吧钥匙
控制数据库链接
semaphore = threading.BoundedSemaphore(5)
#_*_coding:utf-8_*_
__author__ = 'jianzuo'
#_*_coding:utf-8_*_
import threading
import time
def run(n):
semaphore.acquire()
time.sleep(1)
print "run the thread :%s\n " % n
semaphore.release()
if __name__ == '__main__':
num = 0
semaphore = threading.BoundedSemaphore(5)
for i in range(30):
t = threading.Thread(target=run,args=(i,))
t.start()
while threading.active_count != 1 #一个程序至少有一个进程一个线程。所以等于1 就会结束
pass
else:
print '-----all thread done-----'
print '---->',num
守护线程 守护线程 守护线程程宕掉,它所产生的子线程没有存在意义 用于控制子线程
import time,threading
def f1():
pass
def f2(arg1,arg2):
time.sleep(3)
print(4+5)
b = time.time()
print(b - a)
f1()
a = time.time()
# 上面默认是 setDaemon(False) 即 主线程会handle住,一直等待多线程执行完毕
# 如果不想让 主线程等待子线程,那么我们直接在start之前 改t.setDaemon(True) 即可
t= threading.Thread(target=f2,args=(1,2,))
t.setDaemon(True)
t.start()
t = threading.Thread(target=f2,args=(1,2,))
t.setDaemon(True)
t.start()
t = threading.Thread(target=f2,args=(1,2,))
t.setDaemon(True)
t.start()
守护线程脚本讲解
我的一个main_thread 主线程产生10个子线程,如果主线程不是守护进程,他们都是并发,执行完才会走下一个主进程,如果设置为守护进程,一旦执行下一个主线程,代表main_thread结束,其他线程执行多少算多少。
#_*_coding:utf-8_*_
__author__ = 'jianzuo'
import threading
import time
def run(num):
if not num == 5:
time.sleep(1)
print " hi i am thread %s ...lalala \n" % num
def main(n):
print "------running main thread----------"
for i in range(10):
t = threading.Thread(target=run,args=(i,))
t.start()
#time.sleep(3)
print "------done main thread----------"
main_thread = threading.Thread(target=main,args=(10,)) #主线程产生10个子线程
main_thread.setDaemon(True) #将主线程设置为守护线程
main_thread.start()
time.sleep(2)
print '\n------->>>>>' #顶格的都是主线程
Lock、Rlock类
由于线程之间随机调度:某线程可能在执行n条后,CPU接着执行其他线程。为了多个线程同时操作一个内存中的资源时不产生混乱,我们使用锁。
Lock(指令锁)是可用的最低级的同步指令。Lock处于锁定状态时,不被特定的线程拥有。Lock包含两种状态——锁定和非锁定,以及两个基本的方法。
可以认为Lock有一个锁定池,当线程请求锁定时,将线程至于池中,直到获得锁定后出池。池中的线程处于状态图中的同步阻塞状态。
RLock(可重入锁)是一个可以被同一个线程请求多次的同步指令。RLock使用了“拥有的线程”和“递归等级”的概念,处于锁定状态时,RLock被某个线程拥有。拥有RLock的线程可以再次调用acquire(),释放锁时需要调用release()相同次数。
可以认为RLock包含一个锁定池和一个初始值为0的计数器,每次成功调用 acquire()/release(),计数器将+1/-1,为0时锁处于未锁定状态。
简言之:Lock属于全局,Rlock属于线程。
构造方法:Lock(),Rlock(),推荐使用Rlock()
实例方法: acquire([timeout]): 尝试获得锁定。使线程进入同步阻塞状态。
release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。
例子一(未使用锁):
#coding:utf-8
importthreadingimporttime
gl_num=0defshow(arg):globalgl_num
time.sleep(1)
gl_num+=1
printgl_numfor i in range(10):
t= threading.Thread(target=show, args=(i,))
t.start()print 'main thread stop'未使用锁
未使用锁
main thread stop9Process finished with exit