python thread practices

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

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

def timer(no,interval): 
  cnt=0 
  
  while cnt    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’ %(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)+” 
      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引入”””

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2281679.html

(0)
上一篇 2025年2月27日 18:51:02
下一篇 2025年2月24日 15:16:36

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • Python的中文字符乱码

    打算用python解析一下网络日志文件。 必然地遇上了中文乱码的问题。 小弟以前学Java,用Python解决中文乱码的问题真不知道如何入手。 在Java下面调试通过的代码,放在Python环境下就给我闹脾气了。   立即学习“Python…

    编程技术 2025年2月27日
    200
  • Python 发送邮件 smtplib

    可以利用smtplib模块来实现发送邮件的功能,一个比较简单的实例代码如下: # Import smtplib for the actual sending functionimport smtplib# Import the email …

    编程技术 2025年2月27日
    200
  • 判断一字符串是否对称,如:abccba

    # 1.判断一字符串是不是对称的,如:abccbadef is_symmetrical(str):length = len(str)for index in range(length / 2):if str[index] == str[le…

    编程技术 2025年2月27日
    200
  • Python线程整理

    线程有五种状态  新建、就绪、运行、阻塞、死亡。  阻塞有三种情况:  同步阻塞是指处于竞争锁定的状态,线程请求锁定时将进入这个状态,一旦成功获得锁定又恢复到运行状态; 等待阻塞是指等待其他线程通知的状态,线程获得条件锁定后,调用“等待”将…

    编程技术 2025年2月27日
    200
  • python xapian存储结构

    在项目中为了支持搜索服务,我们使用xapian作为后端的搜索引擎.其因性能良好以及易用受到大家欢迎.下面是基本代码:  import xapianimport posixpathdef get_db_path():    XAPIAN_RO…

    编程技术 2025年2月27日
    200
  • python中的国际化使用

    # -*- coding: utf-8 -*-#!/usr/bin/env python”’1.run “python pygettext.py”, will generate file messages.pot2.open messag…

    编程技术 2025年2月27日
    200
  • python gevent实现机制

    之前看的greenlet只是提供了基本的coroutine的作用,是最小的执行单元.但是要想使用,还需要提供一个调度器,来调度什么时候哪些greenlet应该执行.所以看了一下gevent的实现,当前的稳定版本使用的是libev.libev…

    编程技术 2025年2月27日
    200
  • from module import 和 import 的区别

    最近在用codecademy学python,遇到一些题目错误,小小记录一下  如from math import sqrt是把sqrt作为本文件的方法导入进来了,使用的时候只需要直接调用sqrt。 而如果import是import math…

    编程技术 2025年2月27日
    200
  • 短URL生成转换

    主要逻辑: 1, 确定一个包括大小写字母、数据的字符串LS,长度为 L = 26+26+10 = 62 2, 初始化L**N个整数,并作为一个序列push到redis里 3, 当需要转换一个长URL时,先从以上的序列中随机pop出一个整数I…

    编程技术 2025年2月27日
    200
  • python greenlet 实现机制

    最近使用python开发web程序,一直使用的是fastcgi模式.然后每个进程中启动多个线程来进行请求处理.这里有一个问题就是需要保证每个请求响应时间都要特别短,不然只要多请求几次慢的就会让服务器拒绝服务,因为没有线程能够响应请求了.平时…

    编程技术 2025年2月27日
    200

发表回复

登录后才能评论