Python学习笔记(二十二):

  1. 信号量
  2. 条件变量(Condition)
  3. 同步条件(Event)
  4. 队列(queue)
  5. FTP作业

1. 信号量

  • 代码示例:
import threading
import time

class myThread(threading.Thread):
    def run(self):
        if semaphore.acquire():
            print(self.name)
            time.sleep(5)
            semaphore.release()

if __name__ == "__main__":
    # 创建信号量
    semaphore = threading.BoundedSemaphore(5)
    thrs = []
    for i in range(100):
        thrs.append(myThread())
    for t in thrs:
        t.start()
# 信号量也是一种锁,他是一个可以规定允许进入线程数量的锁,待数量达到规定数量后不能再有其他线程进入锁内。

2. 条件变量(Condition)

  • 代码示例:
import threading
import time
from random import randint

class Producer(threading.Thread):
    def run(self):
        global L
        while True:
            val = randint(0, 100)
            if lock_con.acquire():
                L.append(val)
                lock_con.notify() # 疏通阻塞,继续执行
                lock_con.release()
            print('生产者', self.name, ":Append" + str(val), L)

            time.sleep(3)

class Consumer(threading.Thread):
    def run(self):
        global L
        while True:
            lock_con.acquire()
            if len(L) == 0:
                lock_con.wait() # 制造一个阻塞
            temp = L[0]
            del L[0]
            print('消费者', self.name, ":Delete" + str(temp), L)
            lock_con.release()
            time.sleep(0.25)

if __name__ == "__main__":

    L = []
    # 创建条件变量的锁
    lock_con = threading.Condition()
    threads = []
    for i in range(5):
        threads.append(Producer())
    threads.append(Consumer())
    for t in threads:
        t.start()
    for t in threads:
        t.join()
# wait():条件不满足时调用,线程会释放锁并进入等待阻塞;
# notify():条件创造后调用,通知等待池激活一个线程;
# notifyAll():条件创造后调用,通知等待池激活所有线程。
  • 条件变量也是一把锁,他在一把递归锁上又加了开关,关是wait(),开是notify(),总开关是notifyAll()
  • 一旦程序执行到wait()就会在wait()处设置一个阻塞,而一旦程序执行到notify()就会疏通一个阻塞,一旦notifyAll()执行后会疏通所有阻塞。

3. 同步条件(Event)

  • 代码示例:
import threading, time

class Boss(threading.Thread):
    def run(self):
        print("BOSS:今晚大家都要加班到22:00。")
        event.isSet() or event.set()
        time.sleep(5)
        print("BOSS:<22:00>可以下班了。")
        event.isSet() or event.set()

class Worker(threading.Thread):
    def run(self):
        event.wait()
        print("Worker:哎……命苦啊!")
        event.clear()
        event.wait()
        print("Worker:OhYeah!")

if __name__ == "__main__":
    event = threading.Event() # 设置同步条件Event
    threads = []
    for i in range(5):
        threads.append(Worker())
    threads.append(Boss())
    for t in threads:
        t.start()
    for t in threads:
        t.join()
  • 同步条件和条件变量同步差不多意思,只是少了锁功能,因为同步条件设计于不访问共享资源的条件环境。event=threading.Event():条件环境对象,初始值 为False;
  • event.isSet():返回event的状态值;
  • event.wait():如果 event.isSet()==False将阻塞线程;
  • event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
  • event.clear():恢复event的状态值为False。

4. 队列(queue)

  • 列表存在线程不安全性,在多线程操作过程中数据存在泄漏危险
  • 队列很好的解决了这个问题,队列给数据内置了锁,防止多线程操作时数据泄漏

创建一个“队列”对象
import Queue
q = Queue.Queue(maxsize = 10)
Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。

将一个值放入队列中
q.put(10)
调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为
1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。

将一个值从队列中取出
q.get()
调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。

Python Queue模块有三种队列及构造函数:
1、Python Queue模块的FIFO队列先进先出。 class queue.Queue(maxsize)
2、LIFO类似于堆,即先进后出。 class queue.LifoQueue(maxsize)
3、还有一种是优先级队列级别越低越先出来。 class queue.PriorityQueue(maxsize)

此包中的常用方法(q = Queue.Queue()):
q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get([block[, timeout]]) 获取队列,timeout等待时间
q.get_nowait() 相当q.get(False)
非阻塞 q.put(item) 写入队列,timeout等待时间
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
q.join() 实际上意味着等到队列为空,再执行别的操作

5. FTP作业

  • 要求:
  1. 用户加密认证
  2. 允许同时多用户登陆
  3. 每个用户有自己的家目录,且只能访问自己的家目录
  4. 对用户进行磁盘配额,每个用户的可用空间不同
  5. 允许用户在ftp server上随意切换目录
  6. 允许用户查看当前目录下文件
  7. 允许上传和下载文件,保证文件一致性
  8. 文件传输过程中显示进度条
  9. 附加功能:支持文件的断点续传