多线程介绍和多线程模块

线程的特点:

线程的生命周期

开始

运行

结束

线程的退出:

进程执行完成

线程的退出方法

python的系统推出

模块函数

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

allocate_lock()

exit()

[root@133 managehosts]# vim thread01.py #!/usr/bin/env python
#encoding:utf8
import thread
import time
def func(name , i):for n in xrange(i):print name, ntime.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:utf8
import thread
import time
def func(name , i, l):for n in xrange(i):print name, ntime.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=Falsepassprint lock.locked() #解锁后,值为False
print "Exit main process"[root@133 managehosts]# python thread01.py
声音 画面 00画面 1
声音 1
画面 2
声音 2
画面 3
声音 3
画面 4
声音 4
False
Exit main process[root@133 managehosts]# vim thread02.py
#!/usr/bin/env python
import thread
import 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 2017
hello world Fri Feb 10 20:26:51 2017
hello world Fri Feb 10 20:26:51 2017
hello world Fri Feb 10 20:26:51 2017
hello world Fri Feb 10 20:26:51 2017[root@133 managehosts]# vim thread02.py
#!/usr/bin/env python
import thread
import timedef printworld():for i in range(5):if w_lock.acquire():  #申请world锁,if True为真print 'world',time.ctime() #打印worldh_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',   #打印hellow_lock.release() #释放world锁while h_lock.locked(): #这是主进程,直到hello打印5次后才释放。pass[root@133 managehosts]# python thread02.py
hello world Fri Feb 10 20:29:48 2017
hello world Fri Feb 10 20:29:48 2017
hello world Fri Feb 10 20:29:48 2017
hello world Fri Feb 10 20:29:48 2017
hello 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 thread
import 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,())#启动线程hello
thread.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 2017
hello world Tue Feb 14 14:59:11 2017
hello world Tue Feb 14 14:59:11 2017
hello world Tue Feb 14 14:59:11 2017
hello 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 threading
import 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.py
hello Tue Feb 14 15:42:10 2017 #瞬间打印10行
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
complete

如果添加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 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
hello Tue Feb 14 15:42:10 2017
complete
[root@133 managehosts]# vim threading02.py
#!/usr/bin/env python
#encoding:utf8
import threading
import time
def func(name, i):for n in xrange(i):print name, ntime.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,然后再打印t2
t1.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 threading
import timedef func(name, i):for n in xrange(i):print name, ntime.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 python
import threading
import time
def 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.py
hello world Wed Mar 29 11:51:59 2017
hello world Wed Mar 29 11:51:59 2017
hello world Wed Mar 29 11:51:59 2017
hello world Wed Mar 29 11:51:59 2017
hello world Wed Mar 29 11:51:59 2017
#!/usr/bin/python
import thread
import 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 countertime.sleep(1)mutex.acquire() #获得锁counter +=1print "I am %s, set counter:%s" %(self.name,counter)mutex.release() #释放锁if __name__ == '__main__':counter = 0mutex = threading.Lock() #分配锁for i in xrange(300):t = MyThread()t.start()[root@133 managehosts]# python threading08.py
I am Thread-1, set counter:1
I am Thread-2, set counter:2
I am Thread-3, set counter:3
I am Thread-4, set counter:4
I am Thread-5, set counter:5
I am Thread-6, set counter:6
I am Thread-7, set counter:7
I am Thread-8, set counter:8
I am Thread-9, set counter:9
I am Thread-10, set counter:10
I am Thread-11, set counter:11
I am Thread-12, set counter:12
I am Thread-13, set counter:13
I am Thread-14, set counter:14
I am Thread-15, set counter:15I am Thread-284, set counter:282
I am Thread-283, set counter:283
I am Thread-282, set counter:284
I am Thread-285, set counter:285
I am Thread-287, set counter:286
I am Thread-286, set counter:287
I am Thread-288, set counter:288
I am Thread-289, set counter:289
I am Thread-290, set counter:290
I am Thread-293, set counter:291
I am Thread-292, set counter:292
I am Thread-291, set counter:293
I am Thread-295, set counter:294
I am Thread-296, set counter:295
I am Thread-297, set counter:296
I am Thread-294, set counter:297
I am Thread-298, set counter:298
I am Thread-299, set counter:299
I am Thread-300, set counter:300

转载于:https://blog.51cto.com/daixuan/1896770

多线程介绍和多线程模块-lock-互斥锁相关推荐

  1. Linux多线程编程---线程间同步(互斥锁、条件变量、信号量和读写锁)

    本篇博文转自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了 ...

  2. 31 多线程同步之Lock(互斥锁)

    如果多个线程共同对某个数据修改,则可能出现不可预测的结果,这个时候就需要使用互斥锁来进行同步.例如,在三个线程对共同变量num进行100万次加减操作之后,其num的结果不为0. [示例 1]不加锁的意 ...

  3. c++11 多线程编程(三)------ 竞争和互斥锁

    竞争条件 并发代码中最常见的错误之一就是竞争条件(race condition).而其中最常见的就是数据竞争(data race),从整体上来看,所有线程之间共享数据的问题,都是修改数据导致的,如果所 ...

  4. 多线程介绍与threading模块应用以及使用Thread类创建多线程

    1.多线程: 多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率.线程是在同一时间需要完成多项任务的时候实现的. 最简单的比喻多线程就像火车的每一节车厢,而进 ...

  5. 【C++】多线程互斥锁、条件变量

    我们了解互斥量和条件变量之前,我们先来看一下为什么要有互斥量和条件变量这两个东西,了解为什么有这两东西之后,理解起来后面的东西就简单很多了!!! 先来看下面这段简单的代码: int g_num = 0 ...

  6. python互斥锁原理_python并发编程之多进程1------互斥锁与进程间的通信

    一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...

  7. POSIX互斥锁自旋锁

    基础组件-POSIX互斥锁自旋锁 基础组件 基础组件-POSIX互斥锁自旋锁 前言 一.互斥锁 二.自旋锁 特点: 场景: 使用原则 自旋锁属性 三.两把锁的区别 1. 调度策略 2.使用场景 四.常 ...

  8. python进程通信方式有几种_python全栈开发基础【第二十一篇】互斥锁以及进程之间的三种通信方式(IPC)以及生产者个消费者模型...

    一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...

  9. Python | threading02 - 互斥锁解决多个线程之间随机调度,造成“线程不安全”的问题。

    文章目录 一.前言 二.线程不安全的现象 2.1.代码 2.2.运行 三.使用互斥锁解决线程不安全 3.1.代码 3.2.运行 四.忘记释放互斥锁,造成死锁 4.1.代码 4.2.运行 4.3.造成死 ...

最新文章

  1. PHP中的traits
  2. 西门子Step7找不到有效授权的解决方法
  3. 集合上二元关系性质判定的实现(python实现)
  4. 1. 赋值运算符函数
  5. .NetCore中三种注入生命周期的思考
  6. linux服务器之间文件复制命令
  7. 取余运算(信息学奥赛一本通-T1326)
  8. leetcode —— 1290. 二进制链表转整数
  9. pyqt5 python qlineedit信号_Pyqt5_QlineEdit
  10. [译] 正确实现 linkedPurchaseToken 以避免重复订阅
  11. ad18常用快捷键可以修改吗_常用发泡剂之聚氨酯发泡剂在冬季可以用吗?
  12. JS中的算法与数据结构——排序(Sort)
  13. 苹果mac3D模型渲染软件:KeyShot
  14. 3.软件架构设计:大型网站技术架构与业务架构融合之道 --- 语言
  15. fastjson笔记
  16. 股票模拟交易软件之手机炒股软件排行榜
  17. OpenV$P$N服务器添加客户端
  18. 动能方案|RFID动物耳标解决方案
  19. 超级牛的网站同步工具软件—端端Clouduolc
  20. 修改多台远程服务器,电脑默认用户名Administrator

热门文章

  1. 图书漂流系统的设计和研究_研究在设计系统中的作用
  2. 护肤产生共鸣_通过以人为本的设计编织共鸣的20个指针
  3. HTTP Server Error 500 内部服务器错误
  4. vue的移动app项目中,自定义拖拽指令的问题
  5. DataArtisans战略联手阿里云 Apache Flink服务能力云化
  6. springmvc_3(将数据放入map中)
  7. 看了《OCP/OCA认证考试指南全册:Oracle Database 11g(1Z0-051,...
  8. NetBeans 6.5 正式发布
  9. .NET(c#) 移动APP开发平台 - Smobiler(1)
  10. netty实现客户端服务端心跳重连