2020-11-04-线程安全-锁-队列-多进程和多线程

day8-线程安全-锁-队列-多进程和多线程
一、线程安全的起因:多个线程可以同时操作同一个数据
解决方法:枷锁
LOCK 锁 - RLOCK锁

首先要导入锁

from threading import Lock,RLock

1.保证一个数据对应一个锁对象

锁对象.Lock()

2.线程在第一次操作数据前加锁

锁对象.acquire()

3.线程在结束数据操作后解锁

锁对象.release()
RLOCK锁

1.保证一个数据对应一个锁对象

锁对象.RLock()

2.将对数据进行操作的代码放大要加锁的范围

with 锁对象:
	操作数据的代码块
二、队列的使用
from queue import Queue

1.什么是队列

a.Queue是一种容器,一般用于多线程多进程的数据共享,因为你Queue对象本身有线程安全

b.获取队列中的元素的时候,如果没有元素会等待,直到队列中有元素为止

2.操作队列

a.添加元素: 队列对象.put(元素)

b.获取元素:队列对象.get()

queue = Queue()

queue.put(元素)   - 添加元素
queue.get()  - 获取元素
线程与进程区别
  • 进程是资源分配的基本单位,线程是CPU执行和调度的基本单位

    • 通信/同步方式:

      • 进程:
        • 通信方式:管道,FIFO,消息队列,信号,共享内存,socket,stream流;
        • 同步方式:PV信号量,管程
      • 线程:
        • 同步方式:互斥锁,递归锁,条件变量,信号量
        • 通信方式:位于同一进程的线程共享进程资源,因此线程间没有类似于进程间用于数据传递的通信方式,线程间的通信主要是用于线程同步。
多线程
import time
from datetime import datetime
from threading import Thread

def download(name):
    print(f'{name}开始下载.{datetime.now()}')
    time.sleep(2)
    print(f'{name}下载结束.{datetime.now()}')

进程默认有一个线程,这个线程叫主线程;其他的线程都叫子线程

python中threading模块中Thread类的对象就是线程对象 (程序中需要多少个线程就创建多少个Thread类或者他的子类的对象)

  1. 创建线程对象

    • Thread(target=函数,args=参数)

    • 函数 - 需要在子线程中调用的函数(普通函数,匿名函数)

    • 参数 - 传一个 元组,默认是();元组中的元素就是调用函数的时候需要传递的实参

    t1 = Thread(target=download,args=('复仇',))
    t2 = Thread(target=download,args=('信条',))
    
  2. 启动线程 - 在子线程中执行任务 线程对象.start()

    t1.start()
    t2.start()
    
  3. 我们可以通过join方法让主线程阻塞,等待其创建的线程执行完成。

    import threading
    import time
    
    def tstart(arg):
        print("%s running....at: %s" % (arg,time.time()))
        time.sleep(1)
        print("%s is finished! at: %s" % (arg,time.time()))
    
    if __name__ == '__main__':
        t1 = threading.Thread(target=tstart, args=('This is thread 1',))
        t1.start()
        t1.join()   # 当前线程阻塞,等待t1线程执行完成
        print("This is main function at:%s" % time.time())
    

    执行结果为:

    This is thread 1 running....at: 1564906617.43
    This is thread 1 is finished! at: 1564906618.43
    This is main function at:1564906618.43
    
线程池
  1. 创建任务列表

    makeRequests(任务对应的函数,参数列表)

    1)任务函数有且只有一个参数2)参数列表中元素的个数决定了任务列表中任务的个数

    tasks = makeRequests(download,[f'电影{x}' for x in range(100)]
    
  2. 创建线程池对象 ThreadPool(线程的数量)

    pool = ThreadPool(10)
    
  3. 在线程池中添加任务 线程池对象.putRequest(任务对象)

    for task in tasks:
        pool.putRequest(task)
    
进程池
 # 1.创建进程池
    # Pool(进程数量)
    pool = Pool(3)

    # 2.添加任务(任务添加完成后会自动启动)
    # 1)一次性添加多个任务(和主进程同步执行)
    # 进程池对象.map(函数,参数列表)
    pool.map(download,[f'电影{x}' for x in range(5)])
    # 一次添加一个任务
    pool.apply(download,('肖生克的救赎',))

    # 3.关闭进程池
    # 进程池关闭后不能再往进程池中添加任务
    pool.close()

    # 4.等待
    pool.join()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值