多线程
多线程创建
- 通过函数 使用threading模块中Thread类中target参数,需要制定接受一个函数对象,函数就是执行子线程的逻辑
- 通过类 自定义类继承threading.Thread类 并覆盖run()方法中来实现线程的逻辑 通过面向对象的编程方式,如果你的子线程比较多 比较方便管理代码
1 | import time |
主线程与子线程的关系
- 主线程会等待子线程执行结束后再结束
1 | import threading |
- 守护线程 setDaemon(True) 不会等待子线程结束
1 | import threading |
- .join() 等待线程结束后主线程再进行
1 | def demo(): |
查看线程数量
- threading.enumerate 查看线程数量
1 | import threading |
子线程的执行与创建
1 | import threading |
通过类创建多线程
1 | import threading |
多线程的资源竞争
1 | import threading |
上锁
互斥锁
因多线程几乎同时修改某一共享数据的时候 需要进行同步控制,某个线程要更改数据时,先将其锁定,此时资源状态为锁定,其他线程不能改变,直到该线程释放资源,其他线程才能再次锁定资源
mutex = threading.Lock() #创建锁 只可执行一次 #mutex = threading.RLock() #可以执行多次 # 加锁 mutex.acquire() # 解锁 mutex.release() <!--hexoPostRenderEscape:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">```python</span><br><span class="line">import threading</span><br><span class="line">import time</span><br><span class="line"># 线程是共享全局变量</span><br><span class="line">num = 0</span><br><span class="line"># 用Lock()方式创建的锁叫做不可重复的锁,只能执行一次</span><br><span class="line">mutex = threading.Lock()</span><br><span class="line">def demo1(nums):</span><br><span class="line"> global num</span><br><span class="line"> # 加锁</span><br><span class="line"> mutex.acquire()</span><br><span class="line"> for i in range(nums):</span><br><span class="line"> num += 1</span><br><span class="line"> # 解锁</span><br><span class="line"> mutex.release()</span><br><span class="line"> print('demo1-num-%d'%num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def demo2(nums):</span><br><span class="line"> global num</span><br><span class="line"> # 加锁</span><br><span class="line"> mutex.acquire()</span><br><span class="line"> for i in range(nums):</span><br><span class="line"> num += 1</span><br><span class="line"> # 解锁</span><br><span class="line"> mutex.release()</span><br><span class="line"> print('demo2-num-%d' % num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line"> t1 = threading.Thread(target=demo1,args=(1000000,)) #demo1-num-1000000</span><br><span class="line"> t2 = threading.Thread(target=demo2,args=(1000000,)) #demo2-num-2000000</span><br><span class="line"> t1.start()</span><br><span class="line"> t2.start()</span><br><span class="line"> time.sleep(3)</span><br><span class="line"> print('main-num-%d'%num)</span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure>:hexoPostRenderEscape-->
死锁
- 在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源就会造成死锁
1 | import threading |
生产者消费者模型
Queue线程
- 在线程中,访问一些全局变量,加锁是一个经常的过程。如果你是想把一些数据存储到某个队列中,那么Python内置了一个线程安全的模块叫做queue模块。Python中的queue模块中提供了同步的、线程安全的队列类,包括FIFO(先进先出)队列Queue,LIFO(后入先出)队列LifoQueue。这些队列都实现了锁原语(可以理解为原子操作,即要么不做,要么都做完),能够在多线程中直接使用。可以使用队列来实现线程间的同步。
- empty():判断队列是否为空。
- full():判断队列是否满了。
- get():从队列中取最后一个数据。
- put():将一个数据放到队列中。
生产者与消费者
- 生产者和消费者模式是多线程开发中常见的一种模式。通过生产者和消费者模式,可以让代码达到高内聚低耦合的目标,线程管理更加方便,程序分工更加明确。
- 生产者的线程专门用来生产一些数据,然后存放到容器中(中间变量)。消费者在从这个中间的容器中取出数据进行消费
Lock版本生产者与消费者
1 | import threading |
Condition版生产者与消费者
1 | import threading |