Python多线程学习(中)

今天接着写多线程,最近几天一直在看多线程,但是书上的例子太难看了(可能我天生愚笨吧~_~),看了好久才搞懂,我看了两本书才搞明白书上的例子,所以大家在看书学习看不懂的时候,推荐多看几本一样知识点的书,在网上多看教程,辅助学习。

下面开始介绍锁和条件变量。

一。“锁”

锁是指在运行程序时,对于需要访问共享资源的多线程程序,为防止I/O密集型操作造成结果发生错误。

使用锁的方法:  import threading

引入锁 lock = threading.Lock()

添加锁  lock.acquire()

对临界资源进行访问的代码

释放锁 lock.release()

假设对数字进行迭代输出,在不加锁的情况下,会导致输出全为15,加锁后是1,2,3,4.。。。。。13,14,15,最后输出‘all done‘

对于添加锁,添加锁后就只能一个线程对公共资源进行访问,所以在执行时速度会变慢,因为执行时等同于同步运行。

示例一代码:

#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-
#导入模
import threading
import time
from atexit import register
import random
lock = threading.Lock()
a = 0
def print_sum():
    global a
    lock.acquire()
    a += 1
    time.sleep(1)
    print(str(a))
    lock.release()
def main():
    th_list = []
    for x in range(15):
        t = threading.Thread(target=print_sum,args=())
        th_list.append(t)
    for x in th_list:
        x.start()
@register
def exit():
    print(‘all done‘)
if __name__ == ‘__main__‘:
    main()

二。条件变量

对于条件变量,可以添加一个判断条件,如果符合条件就执行,否则等待。

导入模块 from threading import Condition

该模块有acquirre()和release(),在不符合条件时,调用.wait(),此时线程就会挂起,调用.notify() 或.notify_all()来激活线程,再进行条件判断。

以消费--生产问题来进行对条件变量讨论。创建一个产品类,一个消费者类,一个生产者类,消费者有五个线程,生产者有一个线程,生产者不断生产,消费者持续消费,不会存在无限生产消费不完的问题,但是停止程序需要手动完成。

代码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import threading
import time
import random

#条件变量,消费者和生产者
#产品类
class Chan_pin():
    def __init__(self):
        self.count = 0
    #消费产品
    def xiao_fei(self):
        self.count -= 1
    #生产产品
    def sheng_chan(self):
        self.count += 1
    #判断产品是否为空
    def pan_duan(self):
        return not self.count
    pass

#生产类
class Sheng_chans(threading.Thread):
    def __init__(self,tiao_jian,chan_pin):
        super().__init__()
        self.tiao_jian = tiao_jian
        self.chan_pin = chan_pin
    def run(self):
        while True:
            self.tiao_jian.acquire()
            self.chan_pin.sheng_chan()
            print(‘已生产的产品数:%s‘ % self.chan_pin.count)
            self.tiao_jian.notify_all()
            self.tiao_jian.release()
            time.sleep(random.random())
    pass
#创建消费类
class Xiao_fei(threading.Thread):
    def __init__(self,chan_pin,tiao_jian):
        super().__init__()
        self.tiao_jian = tiao_jian
        self.chan_pin = chan_pin
    #重构run函数
    def run(self):

        while True:
            self.tiao_jian.acquire()
            time.sleep(random.randint(2,5))
            if self.chan_pin.pan_duan():
                self.tiao_jian.wait()
                print(‘%s产品没了,请等待。。。‘ % threading.current_thread().name)
            else:
                self.chan_pin.xiao_fei()
                print(‘%s已消费,现剩余产品:%s‘ % (threading.current_thread().name,self.chan_pin.count))
                self.tiao_jian.notify_all()
                self.tiao_jian.release()
    pass

#创建实例。
def main():
    tiao_jian = threading.Condition()
    chan_pin = Chan_pin()
    t1 = Sheng_chans(tiao_jian,chan_pin)
    t1.start()
    time.sleep(5)
    #t1.join()
    for x in range(5):
        t2 = Xiao_fei(chan_pin,tiao_jian)
        t2.start()
        print(threading.active_count())
        print(threading.enumerate())
    print(threading.enumerate()[-2].is_alive())
        #t2.join()

#运行
if __name__ == ‘__main__‘:
    main()

  

三。信号量

信号量允许添加指定个数的线程对公共资源进行访问。

对于信号量有两个模块可用,分别是:Semaphore和BoundedSemaphore 前一个模块比第二个有一个缺点,第一个在进行调用.release()时,添加数超过设定数时不会报错,而第二个会进行报错。

本文章主要对第二个进行介绍。

该模块有两个方法,  .acquire()和.release()  在调用.acquire()时会减一,当减到0时,会停止线程运行,进入等待;调用.release()时会加一。

调用方法:

num = 5    #表示只允许5个线程对公共资源进行访问。

a = BoundedSemaphore(num)

a.acquire()

要执行的代码

a.release()

下面是示例代码:

 1 #!/usr/bin/env python3.6
 2 # -*- coding: utf-8 -*-
 3 #导入模
 4 import threading
 5 import time
 6 from atexit import register
 7
 8
 9 #要操作的公共资源,设置一个列表,多个线程对列表进行访问,输出列表内容。
10
11 num = 3
12 a = threading.BoundedSemaphore(num)
13 #创建一个输出内容的函数
14 def print_list(list):
15     a.acquire()
16     p = threading.current_thread().name
17     if a.acquire(False):
18         print(‘%s : 不能运行‘ % p)
19     else:
20         print(‘%s:%s‘ % (p,list))
21     a.release()
22
23 #继承线程类
24 class New_thread(threading.Thread):
25     def __init__(self,han_name,han_can):
26         super().__init__()
27         self.han_name = han_name #函数名
28         self.han_can = han_can  #要传入函数的参数
29     def run(self):
30         self.han_name(self.han_can)
31     pass
32
33 #
34 def main():
35     list_1 = [‘aaaa‘, ‘bbbb‘, ‘cccc‘, ‘dddd‘, ‘eeee‘, ‘ffff‘]
36     #线程列表
37     thread_list = []
38     #创建十个线程
39     for x in range(5):
40         t = New_thread(print_list,list_1)
41         thread_list.append(t)
42     for x in thread_list:
43         x.start()
44     #print(thread_list)
45
46 #创建回调函数。
47 @register
48 def exit():
49     print(‘all done‘)
50
51 if __name__ == ‘__main__‘:
52     main()

以上就是关于多线程的锁,信号量,条件变量,有不对的地方还望多指教。

原文地址:https://www.cnblogs.com/sniper-huohuohuo/p/8854833.html

时间: 2024-10-11 10:45:47

Python多线程学习(中)的相关文章

python多线程学习记录

1.多线程的创建 import threading t = t.theading.Thread(target, args--) t.SetDeamon(True)//设置为守护进程 t.start(),启动线程 t.join(),阻塞当前线程,即使得在当前线程结束时,不会退出.会等到子线程结束之后才退出. 如果不加join语句,主线程不会等到子线程结束才结束,但却不会立即杀死该线程. 但是如果添加了SetDaemon(True),如果不加join,则会在主线程结束后马上杀死子线程. 如果join

Python多线程学习资料1

一.Python中的线程使用: Python中使用线程有两种方式:函数或者用类来包装线程对象. 1.  函数式:调用thread模块中的start_new_thread()函数来产生新线程.如下例: view plaincopy to clipboardprint? import time import thread def timer(no, interval): cnt = 0 while cnt<10: print 'Thread:(%d) Time:%s\n'%(no, time.cti

python初步学习中的问题之HTTP status code is not handled or not allowed

按照网上的教程学习python,最开始的dmoz_spider项目一直不能正常运行,一直出现下面的问题: 即http status code is not handled or allowed http状态代码没有被处理或允许, 一开始我不理解,在网上找了好多修改setting.py中的 DOWNLOADER_MIDDLEWARES方法也没啥用,心疼自己英语太差,好多问题看不懂... 不过最后还是找到了修改方法: 就是你的http状态码没有被识别,需要在settings.py中添加这个状态码信息

python程序学习中

python 网站,尤其是百度这一块大多基于2.0,想学习思路或者处理方式,都要写2.0的,然后在3.5的各种报错,为了更好的重整框架,一些语言是不支持向上兼容的,这也是一个好事 慢慢的你在了解语言的调整,你跟着去修改你的程序,慢慢的就会熟悉掌握很多东西 我就很享受去体会这种差异,给变成人生带来一种思考的跨越,当然是体会别人思考的跨越,为何会这样更改,我们在学习阶段,没有理由去怀疑别人,全盘接受.就像钢琴,在初级阶段,你必须保持良好的手型,你看大师,好像没有手型,你很羡慕,其实呢,能在告诉移动中

Python 多线程学习(转)

转自:http://www.cnblogs.com/slider/archive/2012/06/20/2556256.html 引言 对于 Python 来说,并不缺少并发选项,其标准库中包括了对线程.进程和异步 I/O 的支持.在许多情况下,通过创建诸如异步.线程和子进程之类的高层模块,Python 简化了各种并发方法的使用.除了标准库之外,还有一些第三方的解决方案,例如 Twisted.Stackless 和进程模块.本文重点关注于使用 Python 的线程,并使用了一些实际的示例进行说明

Python多线程学习

一.Python中的线程使用:     Python中使用线程有两种方式:函数或者用类来包装线程对象. 1.  函数式:调用thread模块中的start_new_thread()函数来产生新线程.如下例: import time import thread def timer(no, interval): cnt = 0 while cnt<10: print 'Thread:(%d) Time:%s\n'%(no, time.ctime()) time.sleep(interval) cnt

Java多线程学习中遇到的一个有趣的问题

今天随便写了一个线程之间相互调度的程序,代码如下: class First extends Thread { public First() { start(); } synchronized public void run() { try { wait(); } catch(InterruptedException e) { e.printStackTrace(); } try { sleep(2000); } catch(InterruptedException e) { e.printSta

Python学习之(二) Python多线程学习

多线程的一个实例 #coding=utf-8 #!/usr/bin/python import time import thread def timer(no, interval): cnt = 0 while cnt<10: time.sleep(interval) print 'Thread:(%d) Time:%s' % (no, time.ctime()) cnt+=1 thread.exit_thread() def test(): #Use thread.start_new_thre

Python 多线程学习

个人总结创建多线程步骤: 1. import threading 2. 创建线程列表 threads = [] 3. 开辟线程 t1 = threading.Thread(…………) 这里注意用args传参是个元组 4. for t in threads循环线程列表,在循环体中用t.setDaemon(True)设置为守护线程后,如果不设置为守护线程程序会被无限挂起,在调用t.start()开始 5. 在for循环外用t.jion()阻塞父线程 class threading.Thread()说