热门IT资讯网

多线程介绍和多线程模块-lock-互斥锁

发表于:2024-11-26 作者:热门IT资讯网编辑
编辑最后更新 2024年11月26日,多线程介绍和多线程模块线程的特点:线程的生命周期开始运行结束线程的退出:进程执行完成线程的退出方法python的系统推出模块函数start_new_thread(func, args) #(func,

多线程介绍和多线程模块


线程的特点:

线程的生命周期

开始

运行

结束


线程的退出:

进程执行完成

线程的退出方法

python的系统推出


模块函数

start_new_thread(func, args) #(func,(name,i))

allocate_lock()

exit()

[root@133 managehosts]# vim thread01.py #!/usr/bin/env python#encoding:utf8import threadimport timedef func(name , i):    for n in xrange(i):        print name, n        time.sleep(1)thread.start_new_thread(func,('声音', 3)) #(func,(name , i))thread.start_new_thread(func,('画面', 3))time.sleep(3)[root@133 managehosts]# python thread01.py 声音 0画面 0声音 1画面 1声音 2画面 2


LockType对象方法

lock= thread.allocate_lock() 生成锁对象

lock.acquire() 加锁

lock.locked() 查看锁状态

lock.release() 多线程调度释放锁,使用前线程必须已经获得锁定,否则将抛出异常

[root@133 managehosts]# vim thread01.py #!/usr/bin/env python#encoding:utf8import threadimport timedef func(name , i, l):    for n in xrange(i):        print name, n        time.sleep(1)    l.release()  #release解锁lock = thread.allocate_lock() #申请一把锁lock.acquire()  #获取并使用这把锁thread.start_new_thread(func,('声音', 5, lock))thread.start_new_thread(func,('画面', 5, lock))while lock.locked(): #这是主进程,lock.locked=True,执行pass,主进程一直处于锁定状态,线程执行,直到线程执行完毕,释放锁,lock.locked=False    passprint lock.locked() #解锁后,值为Falseprint "Exit main process"[root@133 managehosts]# python thread01.py 声音 画面 00画面 1声音 1画面 2声音 2画面 3声音 3画面 4声音 4FalseExit main process[root@133 managehosts]# vim thread02.py #!/usr/bin/env pythonimport threadimport timedef printworld():    for i in range(5):        if w_lock.acquire():            print 'world',time.ctime()            h_lock.release()h_lock = thread.allocate_lock()w_lock = thread.allocate_lock()thread.start_new_thread(printworld, ())w_lock.acquire()for i in range(5):    if h_lock.acquire():        print 'hello',        w_lock.release()time.sleep(1)[root@133 managehosts]# python thread02.py hello world Fri Feb 10 20:26:51 2017hello world Fri Feb 10 20:26:51 2017hello world Fri Feb 10 20:26:51 2017hello world Fri Feb 10 20:26:51 2017hello world Fri Feb 10 20:26:51 2017[root@133 managehosts]# vim thread02.py #!/usr/bin/env pythonimport threadimport timedef printworld():    for i in range(5):        if w_lock.acquire():  #申请world锁,if True为真            print 'world',time.ctime() #打印world            h_lock.release()   #释放hello锁h_lock = thread.allocate_lock()w_lock = thread.allocate_lock()thread.start_new_thread(printworld, ()) #开启的线程,和主进程并列执行。w_lock.acquire()   #获得world锁for i in range(5):    if h_lock.acquire(): #申请hello锁,if True为真        print 'hello',   #打印hello        w_lock.release() #释放world锁while h_lock.locked(): #这是主进程,直到hello打印5次后才释放。    pass        [root@133 managehosts]# python thread02.py hello world Fri Feb 10 20:29:48 2017hello world Fri Feb 10 20:29:48 2017hello world Fri Feb 10 20:29:48 2017hello world Fri Feb 10 20:29:48 2017hello world Fri Feb 10 20:29:48 2017


申请了锁之后,会执行thread.start_new_thread(func,('声音',5,lock))和thread.start_new_thread(func,('画面',5,lock))这两行代码的。

执行他们的时候,同时也会执行主进程里的while的。主进程与这两个线程是同时执行的。为了不让线程退出,所以在主进程里有while来判断锁是不是已经释放了,如果是释放了,说明线程执行完了。


使用主线程控制,线程打印hello和world

[root@133 managehosts]# vim thread03.py +22#!/usr/bin/env pythonimport threadimport timedef hello():    for i in xrange(5):        h_lock.acquire()        print 'hello',        w_lock.release()def world():    for i in xrange(5):        w_lock.acquire()        print 'world',time.ctime()        h_lock.release()     lock.release()#释放主线程的的锁lock = thread.allocate_lock() #为主进程申请锁lock.acquire()      #主进程获得锁h_lock = thread.allocate_lock()  #为hello线程申请一把锁w_lock = thread.allocate_lock()  #为world线程申请一把锁w_lock.acquire()                 #world线程获取锁thread.start_new_thread(hello,())#启动线程hellothread.start_new_thread(world,())#启动线程world#time.sleep(1)while lock.locked():   #当主线程的锁的状态为true时     pass               #什么都不做    #hello 和 world 的两个线程是同时运行的   [root@133 managehosts]# python thread03.py hello world Tue Feb 14 14:59:11 2017hello world Tue Feb 14 14:59:11 2017hello world Tue Feb 14 14:59:11 2017hello world Tue Feb 14 14:59:11 2017hello world Tue Feb 14 14:59:11 2017


从脚本的执行顺序,hello()这个函数先执行,输出hello,
然后把world的锁释放(w_lock.release())。
world()函数获得锁,输出world,然后把hello的锁释放。
必须释放对方的锁,对方才能获得锁(h_lock.acquire()),如果对方的锁没有被释放,那么对方再想获得锁是不成功的,会一直处于阻塞状态,直到锁被释放。


hello()函数第一次获得了锁资源(h_lock.acquire()),打印了hello,接着释放了world的锁资源(w_lock.release())。
world()函数获得了锁资源(w_lock.acquire()),打印了world,接着释放了hello的锁资源(h_lock.release())。
由于hello的锁资源被释放了,hello函数里又获得了锁资源,接着第二次打印hello。
也就是说哪个函数或得了锁资源,就会打印相应的信息。
锁资源只有被释放了,下一次才能获得,即已经获得了锁资源,不能再次获得,所以在hello函数里释放world的锁资源,在world函数里才能获得锁资源。
这样反反复复,就打印了hello world。



threading


threading不需要进程的控制来控制线程

threading.Thread:类

成员方法:

start() 启动线程

run() 可以重写

join() 阻塞

getName()

setName()

isDaemon()判断线程是否随主线程一起结束

setDaemon设置线程与主线程一起结束


In [1]: import threadingIn [2]: help(threading.Thread)Help on class Thread in module threading:class Thread(_Verbose) |  Method resolution order: |      Thread |      _Verbose |      __builtin__.object |   |  Methods defined here: |   |  __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None)
[root@133 managehosts]# vim threading01.py#!/usr/bin/env pythonimport threadingimport timedef func():    print 'hello',time.ctime()    time.sleep(1)if __name__ == '__main__':    for i in xrange(10):        t = threading.Thread(target=func, args =())        t.start()print 'complete'    [root@133 managehosts]# python threading01.pyhello Tue Feb 14 15:42:10 2017 #瞬间打印10行hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017complete


如果添加t.join,则会阻塞,每秒打印一次,上一个阻塞执行完才会执行下一个

def func():    print 'hello',time.ctime()    time.sleep(1)if __name__ == '__main__':    for i in xrange(10):        t = threading.Thread(target=func, args =())        t.start()        t.join()[root@133 managehosts]# python threading01.py  hello Tue Feb 14 15:42:10 2017 #每隔一秒打印一次hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017hello Tue Feb 14 15:42:10 2017complete


[root@133 managehosts]# vim threading02.py #!/usr/bin/env python#encoding:utf8import threadingimport timedef func(name, i):    for n in xrange(i):        print name, n        time.sleep(1)t1 = threading.Thread(target=func, args=('声音',3))t2 = threading.Thread(target=func, args=('画面',3))t1.start()t2.start()[root@133 managehosts]# python threading02.py 声音 0画面 0声音 1画面 1声音 2画面 2如果添加一个t1.join(),则会先打印t1,然后再打印t2t1.start()t1.join()t2.start()结果变为:[root@133 managehosts]# python threading02.py 声音 0声音 1声音 2画面 0画面 1画面 2


t1.setDaemon(True) 设置t1线程和主进程一起退出

[root@133 managehosts]# vim threading02.py #!/usr/bin/env python#encoding:utf8import threadingimport timedef func(name, i):    for n in xrange(i):        print name, n        time.sleep(1)t1 = threading.Thread(target=func, args=('声音',3))t2 = threading.Thread(target=func, args=('画面',3))t1.setDaemon(True) #设置t1线程和主进程一起退出t1.start()         #开启t1线程,打印一次就会退出,因为主进程已经退出t2.setDaemon(True)t2.start()[root@133 managehosts]# python threading02.py 声音 0画面 0


互斥锁

[root@133 managehosts]# pwd/opt/python/managehosts[root@133 managehosts]# cat threading07.py#!/usr/bin/env pythonimport threadingimport timedef hello():    for i in xrange(5):        h_lock.acquire()        print 'hello',        w_lock.release()def world():    for i in xrange(5):        w_lock.acquire()        print 'world',time.ctime()        h_lock.release()h_lock =  threading.Lock()w_lock = threading.Lock()w_lock.acquire()t1 = threading.Thread(target=hello, args=())t2 = threading.Thread(target=world, args=())t1.start()t2.start()[root@133 managehosts]# python threading07.pyhello world Wed Mar 29 11:51:59 2017hello world Wed Mar 29 11:51:59 2017hello world Wed Mar 29 11:51:59 2017hello world Wed Mar 29 11:51:59 2017hello world Wed Mar 29 11:51:59 2017
#!/usr/bin/pythonimport threadimport timedef hello():    for i in xrange(5):        h_lock.acquire()        print 'hello',        w_lock.release()def world():    for i in xrange(5):        w_lock.acquire()        print 'world'        h_lock.release()    lock.release()lock = thread.allocate_lock() lock.acquire()    h_lock = thread.allocate_lock()w_lock = thread.allocate_lock()w_lock.acquire()thread.start_new_thread(hello, ())thread.start_new_thread(world, ())while lock.locked():        pass


程序执行开两个线程,即hello和world。

执行hello线程时,只有3步:

  1. 先申请h_lock锁,即h_lock.acquire()

  2. 然后输出hello,即print 'hello',

  3. 最后释放w_lock锁,即w_lock.release()

执行world线程时也是3步:

  1. 申请w_lock锁,即w_lock.acquire()

  2. 输出world,即print 'world'

  3. 释放h_lock锁,即h_lock.release()

线程是同时执行的,为什么hello和world会交替输出,没有先输出world?

在主线程里,申请了w_lock锁,即26行的w_lock.acquire(),所以在world()函数里的w_lock.acquire()一直

处于阻塞状态,意味着print 'world'这一行是不会执行的,直到hello()函数里把w_lock释放,即w_lock.release()

所以在每个函数里都有释放对方的锁,这样对方就把自己要输出的内容执行了。

最后world函数里的循环执行完了,释放lock这个锁,这样这个主进程也结束了。


[root@133 managehosts]# cat threading08.py#!/usr/bin/env pythonimport threadingimport timeclass MyThread(threading.Thread):    def __init__(self):        threading.Thread.__init__(self)    def run(self):        global counter        time.sleep(1)        mutex.acquire() #获得锁        counter +=1        print "I am %s, set counter:%s" %(self.name,counter)        mutex.release() #释放锁if __name__ == '__main__':    counter = 0    mutex = threading.Lock() #分配锁    for i in xrange(300):        t = MyThread()        t.start()        [root@133 managehosts]# python threading08.pyI am Thread-1, set counter:1I am Thread-2, set counter:2I am Thread-3, set counter:3I am Thread-4, set counter:4I am Thread-5, set counter:5I am Thread-6, set counter:6I am Thread-7, set counter:7I am Thread-8, set counter:8I am Thread-9, set counter:9I am Thread-10, set counter:10I am Thread-11, set counter:11I am Thread-12, set counter:12I am Thread-13, set counter:13I am Thread-14, set counter:14I am Thread-15, set counter:15I am Thread-284, set counter:282I am Thread-283, set counter:283I am Thread-282, set counter:284I am Thread-285, set counter:285I am Thread-287, set counter:286I am Thread-286, set counter:287I am Thread-288, set counter:288I am Thread-289, set counter:289I am Thread-290, set counter:290I am Thread-293, set counter:291I am Thread-292, set counter:292I am Thread-291, set counter:293I am Thread-295, set counter:294I am Thread-296, set counter:295I am Thread-297, set counter:296I am Thread-294, set counter:297I am Thread-298, set counter:298I am Thread-299, set counter:299I am Thread-300, set counter:300


0