设为首页 收藏本站
查看: 490|回复: 0

[经验分享] python thread practices

[复制链接]

尚未签到

发表于 2017-4-23 09:14:03 | 显示全部楼层 |阅读模式
materials:http://www.cnblogs.com/holbrook/archive/2012/02/23/2365420.html

"""" Python中使用线程有两种方式:函数或者用类来包装线程对象。

1、  函数式:调用thread模块中的start_new_thread()函数来产生新线程。线程的结束可以等待线程自然结束,也可以在线程函数中调用thread.exit()或thread.exit_thread()方法。
import time
import thread

def timer(no,interval):
  cnt=0
  
  while cnt<10:
    print 'thread(%d)'%(cnt)
    time.sleep(interval)
    cnt=cnt+1
  

def test():
  thread.start_new_thread(timer,(1,1))
  thread.start_new_thread(timer,(2,2))

if __name__=='__main__':
  print 'thread starting'
  test()
  time.sleep(20)
  thread.exit_thread()
  print 'exit...'
2、  创建threading.Thread的子类来包装一个线程对象,
threading.Thread类的使用:

1,在自己的线程类的__init__里调用threading.Thread.__init__(self, name = threadname)

Threadname为线程的名字

2, run(),通常需要重写,编写代码实现做需要的功能。

3,getName(),获得线程对象名称

4,setName(),设置线程对象名称

5,start(),启动线程

6,jion([timeout]),等待另一线程结束后再运行。

7,setDaemon(bool),设置子线程是否随主线程一起结束,必须在start()之前调用。默认为False。

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

9,isAlive(),检查线程是否在运行中。
import threading
import time

class timer(threading.Thread):
  def __init__(self,num,interval):
    threading.Thread.__init__(self)
    self.thread_num=num
    self.interval=interval
    self.thread_stop=False

  def run(self):
    while not self.thread_stop:
      print 'thread object (%d), time %s\n' %(self.thread_num,time.ctime())
      time.sleep(self.interval)

  def stop(self):
    self.thread_stop=True

def test():
  thread1=timer(1,1)
  thread2=timer(2,2)
  thread1.start()
  thread2.start()
  time.sleep(10)
  thread1.stop()
  thread2.stop()
  return

if __name__=='__main__':
  test()
"""
"""
问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期。这种现象称为“线程不安全”。
import threading
import time

class MyThread(threading.Thread):
  def run(self):
    for i in range(3):
      time.sleep(1)
      msg='I am '+ self.getName()+'@'+str(i)
      print msg

def test():
  for i in range(5):
    t=MyThread()
    t.start()

if __name__=='__main__':
  test()

上面的例子引出了多线程编程的最常见问题:数据共享。当多个线程都修改某一个共享数据的时候,需要进行同步控制。

线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。其中,锁定方法acquire可以有一个超时时间的可选参数timeout。如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁,从而可以进行一些其他的处理

threading模块中定义了Lock类
import threading
import time

class MyThread(threading.Thread):
  def run(self):
    global num
    time.sleep(1)

    if mutex.acquire():
      num=num+1
      print self.name+' set num to '+str(num)+'\n'
      mutex.release()
num=0
mutex=threading.Lock()

def test():
  for i in range(5):
    t=MyThread()
    t.start()

if __name__=='__main__':
  test()
"""
"""更简单的死锁情况是一个线程“迭代”请求同一个资源,直接就会造成死锁:
import threading
import time

class MyThread(threading.Thread):
    def run(self):
        global num
        time.sleep(1)

        if mutex.acquire(1):  
            num = num+1
            msg = self.name+' set num to '+str(num)
            print msg
            mutex.acquire()
            mutex.release()
            mutex.release()
num = 0
mutex = threading.Lock()
def test():
    for i in range(5):
        t = MyThread()
        t.start()
if __name__ == '__main__':
    test()
为了支持在同一线程中多次请求同一资源,python提供了“可重入锁”:threading.RLock。RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:
import threading
import time

class MyThread(threading.Thread):
    def run(self):
        global num
        time.sleep(1)

        if mutex.acquire(1):  
            num = num+1
            msg = self.name+' set num to '+str(num)
            print msg
            mutex.acquire()
            mutex.release()
            mutex.release()
num = 0
mutex = threading.RLock()
def test():
    for i in range(5):
        t = MyThread()
        t.start()
if __name__ == '__main__':
    test()
"""

"""
python多线程编程(5): 条件变量同步

互斥锁是最简单的线程同步机制,Python提供的Condition对象提供了对复杂线程同步问题的支持。Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。

可以认为Condition对象维护了一个锁(Lock/RLock)和一个waiting池。线程通过acquire获得Condition对象,当调用wait方法时,线程会释放Condition内部的锁并进入blocked状态,同时在waiting池中记录这个线程。当调用notify方法时,Condition对象会从waiting池中挑选一个线程,通知其调用acquire方法尝试取到锁。

Condition对象的构造函数可以接受一个Lock/RLock对象作为参数,如果没有指定,则Condition对象会在内部自行创建一个RLock。

除了notify方法外,Condition对象还提供了notifyAll方法,可以通知waiting池中的所有线程尝试acquire内部锁。由于上述机制,处于waiting状态的线程只能通过notify方法唤醒,所以notifyAll的作用在于防止有线程永远处于沉默状态。

演示条件变量同步的经典问题是生产者与消费者问题:假设有一群生产者(Producer)和一群消费者(Consumer)通过一个市场来交互产品。生产者的”策略“是如果市场上剩余的产品少于1000个,那么就生产100个产品放到市场上;而消费者的”策略“是如果市场上剩余产品的数量多余100个,那么就消费3个产品。用Condition解决生产者与消费者问题的代码如下:
import threading
import time

class Producer(threading.Thread):
  def run(self):
    global count
    while True:
      if con.acquire():
        if count>1000:
          con.wait()
        else:
          count=count+100
          print self.name+' produce 100,count='+str(count)

        con.release()
        time.sleep(1)

class Customer(threading.Thread):
  def run(self):
    global count
    while True:
      if con.acquire():
        if count>100:
          count=count-100
          print self.name+ 'consume 100, count='+str(count)
        else:
          con.wait()
        con.release()
        time.sleep(1)

count=500
con=threading.Condition()

def test():
  for i in range(5):
    p=Producer()
    p.start()
    c=Customer()
    c.start()
    print i


if __name__=='__main__':
  test()
python中默认全局变量在函数中可以读,但是不能写但是
对con只读,所以不用global引入"""

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-368015-1-1.html 上篇帖子: python 常用函数 下篇帖子: Python-数据类型
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表