Python多线程

原创 2018年04月15日 18:34:33

1.同时执行多个任务

  •     多进程模式
  •     多线程模式
  •     多进程+多线程

   注:进程是操作系统分配资源的最小单元。线程是操作系统调度的最小单元。

2.多线程编程

  • 多任务可以由多进程完成,也可以由一个进程中的多线程完成(一个进程至少有一个进程)

3.Python中模块

  • _thread和threading。_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下我们使用的是threading高级模块

3.启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行

import threading
import time


def loop(x):
    print("%s start" % threading.current_thread().name)
    for i in range(x):
        time.sleep(1)
        print("%s : %d" % (threading.current_thread().name, i))
        # print("%s stop" % threading.current_thread().name)
    print("%s stop" % threading.current_thread().name)


print("%s start" % threading.current_thread().name)
t1 = threading.Thread(target=loop, args=(6,))
t1.start()
print("%s stop" % threading.current_thread().name)

结果:

MainThread start

Thread-1 start
MainThread stop
Thread-1 : 0
Thread-1 : 1
Thread-1 : 2
Thread-1 : 3
Thread-1 : 4
Thread-1 : 5

Thread-1 stop

结果分析:主线程先运行完毕,再运行子线程

4.如果希望主线程等待子线程执行完毕,使用join()方法

import threading
import time


def loop(x):
    print("%s start" % threading.current_thread().name)
    for i in range(x):
        time.sleep(1)
        print("%s : %d" % (threading.current_thread().name, i))
        # print("%s stop" % threading.current_thread().name)
    print("%s stop" % threading.current_thread().name)


print("%s start" % threading.current_thread().name)
t1 = threading.Thread(target=loop, args=(6,))
t1.start()
t1.join()
print("%s stop" % threading.current_thread().name)

结果:

MainThread start
Thread-1 start
Thread-1 : 0
Thread-1 : 1
Thread-1 : 2
Thread-1 : 3
Thread-1 : 4
Thread-1 : 5
Thread-1 stop

MainThread stop

结果分析:MainThread 一直停在join位置,直到子线程运行完毕

6.主线程退出的时候,不管子线程运行到哪里,强制退出子线程,使用setDaemon(True), 这个方法在线程启动之前调用

import threading
import time


def loop(x):
    print("%s start" % threading.current_thread().name)
    for i in range(x):
        time.sleep(1)
        print("%s : %d" % (threading.current_thread().name, i))
        # print("%s stop" % threading.current_thread().name)
    print("%s stop" % threading.current_thread().name)


print("%s start" % threading.current_thread().name)
t1 = threading.Thread(target=loop, args=(6,))
t1.setDaemon(True)
t1.start()
# t1.join()
print("%s stop" % threading.current_thread().name)

结果:

MainThread start
Thread-1 start

MainThread stop

7.线程锁(lock)

多线程和多进程最大的不同在于,多进程同一变量各自有一份拷贝存在每个进程中,互不影响,而多线程所有变量由线程共享,所以任何一个变量都可以由任何一个线程修改,因此线程间共享数据最大的危险在与多个线程同时改变一个变量,把内容给改乱了。解决方法:使用threading.Lock()方法,使用线程锁锁定线程需要使用的对象,确保一次只有一个线程能够使用该对象。

实例:多线程操作同一对象出错

import threading

deposit = 0  # 存款


def change(n):
    global deposit
    deposit = deposit + n
    deposit = deposit - n


def loop(n):
    for i in range(10000000):
        change(n)


t1 = threading.Thread(target=loop, args=(5,))
t2 = threading.Thread(target=loop, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(deposit)

结果:

45

结果分析:t1,t2交替运行,当两个线程同时访问一个对象时候,容易出错


使用线程锁结果该问题:

import threading

deposit = 0  # 存款


def change(n):
    global deposit
    deposit = deposit + n
    deposit = deposit - n


def loop(n):
    for i in range(10000000):
        lock.acquire()  # 取得一个锁
        try:
            change(n)
        finally:
            lock.release()  # 释放一个锁


lock = threading.Lock()  # 创建一个锁对象
t1 = threading.Thread(target=loop, args=(5,))
t2 = threading.Thread(target=loop, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(deposit)

结果:

0

8.线程锁讨论

线程锁确保某段关键代码只能由一个线程从头到尾完整执行,但是线程锁阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率大大降低。其次由于可以存在多个锁,不同线程支持不同的锁,试图获得对方的锁时,可能会造成死锁。

9.全局解释器锁(GIL)

任何python线程执行前都必须获得GIL锁,执行代码直到线程睡眠或者python将它挂起,线程释放GIL。一个处理核心只能在同一时间运行一个线程。Python中可以使用多线程,但不能有效的利用多个处理核心。可以使用多进程来利用多核。

cpu密集型(各种循环,计数等):遇到io操作或者ticks超过100(每执行100条字节码),释放GIL。触发GIL竞争,线程间的来回切换需要消耗资源,故而多线程对CPU密集型代码并不友好。

io密集型(文件处理/网络爬虫):动线程能提升效率(单线程io会进行io等待,造成不必要的时间浪费,开启多线程可以让进程A等待时自动切换到线程B,可以不浪费cpu资源,提升效率)

10.为什么多进程不会有上述情况。

每一个进程都有各自独立的GIL,互不影响。

跟李宁老师学Python视频课程(17):Python 多线程

-
  • 1970年01月01日 08:00

python线程编程

  • 2010年11月29日 23:16
  • 9KB
  • 下载

python threadpool

  • 2012年02月22日 15:39
  • 72KB
  • 下载

python多线程端口扫描器

#!/usr/bin/env python import socket import sys import threading import time NORMAL = 0 ERROR = 1 TI...
  • earbao
  • earbao
  • 2017-01-05 18:00:08
  • 448

Python多线程 - 使用TheadLocal传递参数

# -*- coding:utf-8 -*- """ 一个ThreadLocal变量虽然是全局变量,但每个线程都只能读写自己线程的独立副本,互不干扰。 ThreadLocal解决了参数在一个线程中各...
  • topleeyap
  • topleeyap
  • 2018-01-05 15:16:21
  • 911

python使用多线程实例讲解

说起多线程,你需要知道多进程和多线程的区别,了解多线程的概念,至于这两点,我不打算在本片文章中详述了,不错,因为我懒得整理。。。不了解的请先问度娘 1、普通的单线程: 打个比方,我想做听音乐和...
  • sqc157400661
  • sqc157400661
  • 2017-07-05 17:14:17
  • 1223

python多线程实现——模拟电影院卖票

  • 2017年09月21日 23:16
  • 2KB
  • 下载

Python-多线程

多线程多进程深度学习
  • 2017年08月21日 15:17

python中的多线程----以2个线程卖票为例

#!/usr/bin/python # -*- coding: UTF-8 -*- #目标:线程1和线程2轮流切换卖100张票 import time import threading if _...
  • wickedvalley
  • wickedvalley
  • 2016-08-21 18:25:40
  • 304

python 多线程为什么鸡肋?

什么是全局解释器锁GIL Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python 在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即...
  • u010229420
  • u010229420
  • 2017-02-27 14:38:31
  • 933
收藏助手
不良信息举报
您举报文章:Python多线程
举报原因:
原因补充:

(最多只允许输入30个字)