threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。python当前版本的多线程库没有实现优先级、线程组,线程也不能被停止、暂停、恢复、中断。

1.     threading模块提供的类:

Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local。

2.     threading 模块提供的常用方法:

  threading.currentThread(): 返回当前的线程变量。

  threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。

  threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

3.     threading 模块提供的常量:

  threading.TIMEOUT_MAX 设置threading全局超时时间。

4.     Thread类

  isAlive(): 返回线程是否在运行。正在运行指启动后、终止前。

  get/setName(name): 获取/设置线程名。

  start():  线程准备就绪,等待CPU调度

  is/setDaemon(bool): 获取/设置是后台线程(默认前台线程(False))。(在start之前设置)

    如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,主线程和后台线程均停止

  如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止

  start(): 启动线程。

  join([timeout]): 阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout(可选参数)。

#coding=utf-8
import threading
def thread_job():
print('This is a thread of %s' % threading.current_thread()) def main():
thread = threading.Thread(target=thread_job,) # 定义线程
thread.start() # 让线程开始工作 if __name__ == '__main__':
main()

threading.Thread()

#coding=utf-8
import threading
def thread_job():
print('This is a thread of %s' % threading.current_thread())
def main():
thread = threading.Thread(target=thread_job,) # 定义线程
thread.setDaemon(False)
thread.start() # 让线程开始工作
if __name__ == '__main__':
print("")
main()
print("")
'''output:
1
2
This is a thread of <Thread(Thread-1, started 9424)>
''' #coding=utf-8
import threading
def thread_job():
print('This is a thread of %s' % threading.current_thread())
def main():
thread = threading.Thread(target=thread_job,) # 定义线程
thread.setDaemon(True)
thread.start() # 让线程开始工作
if __name__ == '__main__':
print("")
main()
print("")
'''output:
1
2
'''

setDaemon

#coding=utf-8
import threading
def thread_job():
print('This is a thread of %s' % threading.current_thread()) def main():
thread = threading.Thread(target=thread_job,) # 定义线程
thread.setDaemon(True)
thread.start() # 让线程开始工作
thread.join()
if __name__ == '__main__':
print("")
main()
print("") '''output:
1
This is a thread of <Thread(Thread-1, started daemon 5292)>
2
''' #coding=utf-8
import threading
def thread_job():
print('This is a thread of %s' % threading.current_thread()) def main():
thread = threading.Thread(target=thread_job,) # 定义线程
#thread.setDaemon(True)
thread.start() # 让线程开始工作
thread.join()
if __name__ == '__main__':
print("")
main()
print("")
'''output:
1
This is a thread of <Thread(Thread-1, started 9220)>
2
''' #coding=utf-8
import threading
def thread_job():
print('This is a thread of %s' % threading.current_thread()) def main():
thread = threading.Thread(target=thread_job,) # 定义线程
#thread.setDaemon(True)
thread.start() # 让线程开始工作
#thread.join()
if __name__ == '__main__':
print("")
main()
print("")
'''output:
1
2
This is a thread of <Thread(Thread-1, started 10032)>
'''

join

1、setDaemon默认是False,无论主程序是否执行完,子程序必须都要执行完,只有等主、子程序都执行完才会退出程序(先后关系不一定是按代码至上向下执行---非阻塞式。)

import threading,time
def job1():
global A
for i in range(2):
A+=1
time.sleep(1)
print('job1',A)
def job2():
global A
for i in range(2):
A+=10
time.sleep(2)
print('job2',A)
if __name__== '__main__':
print("begin")
lock=threading.Lock()
A=0
t1=threading.Thread(target=job1)
t2=threading.Thread(target=job2)
t1.start()
t2.start()
print("end") '''output:
begin
end
('job1', 11)
('job2', 12)
('job1', 22)
('job2', 22)
'''

setDaemon

2、setDaemon默认是True,无论子程序是否执行完,主程序只要执行完就会退出程序。(先后关系不一定是按代码至上向下执行---非阻塞式。)

import threading,time
def job1():
global A
for i in range(2):
A+=1
time.sleep(1)
print('job1',A)
def job2():
global A
for i in range(2):
A+=10
time.sleep(2)
print('job2',A)
if __name__== '__main__':
print("begin")
lock=threading.Lock()
A=0
t1=threading.Thread(target=job1)
t2=threading.Thread(target=job2)
t1.setDaemon(True)
t2.setDaemon(True)
t1.start()
t2.start()
print("end") '''output:
begin
end
'''

setDaemon

3、join方法存按代码至上而下先后执行(必须得执行完中间代码的子线程,才会去执行末行主线程代码)---阻塞式

同一线程对象的start和join是否紧挨着区别:

import threading,time
def job1():
print("start the 1st threading")
time.sleep(0.5)
print("1st threading ends")
def job2():
print("start the 2nd threading")
time.sleep(2)
print("2nd threading ends")
def job3():
print("start the 3rd threading")
time.sleep(1)
print("3rd threading ends")
if __name__== '__main__':
print("begins")
lock=threading.Lock()
first = threading.Thread(target=job1)
second = threading.Thread(target=job2)
third = threading.Thread(target=job3)
first.start()
first.join()
second.start()
second.join()
third.start()
third.join()
print("ends")
'''输出:
begins
start the 1st threading
1st threading ends
start the 2nd threading
2nd threading ends
start the 3rd threading
3rd threading ends
ends
'''

同个线程对象的start和join紧挨着

import threading,time
def job1():
print("start the 1st threading")
time.sleep(0.5)
print("1st threading ends")
def job2():
print("start the 2nd threading")
time.sleep(2)
print("2nd threading ends")
def job3():
print("start the 3rd threading")
time.sleep(1)
print("3rd threading ends")
if __name__== '__main__':
print("begins")
lock=threading.Lock()
first = threading.Thread(target=job1)
second = threading.Thread(target=job2)
third = threading.Thread(target=job3)
first.start()
second.start()
third.start()
first.join()
second.join()
third.join()
print("ends") '''输出:
begins
start the 1st threading
start the 2nd threading
start the 3rd threading
1st threading ends
3rd threading ends
2nd threading ends
ends
'''

同一个线程对象的start和join不紧挨着

小结:个人感觉同一线程对象的start和join最好不要紧挨着。

5、Queue

在多线程函数中定义一个Queue,用来保存返回值,代替return,定义一个多线程列表,初始化一个多维数据列表。

import threading
import time from queue import Queue def job(l,q):
for i in range (len(l)):
l[i] = l[i]**2
q.put(l) def multithreading():
q =Queue()
threads = []
data = [[1,2,3],[3,4,5],[4,4,4],[5,5,5]]
for i in range(4):
t = threading.Thread(target=job,args=(data[i],q))
t.start()
threads.append(t)
for thread in threads:
thread.join()
results = []
for _ in range(4):
results.append(q.get())
print(results) if __name__=='__main__':
multithreading()

Queue

6、线程锁

lock在不同线程使用同一共享内存时,能够确保线程之间互不影响,使用lock的方法是, 在每个线程执行运算修改共享内存之前,执行lock.acquire()将共享内存上锁, 确保当前线程执行时,内存不会被其他线程访问,执行运算完毕后,使用lock.release()将锁打开, 保证其他的线程可以使用该共享内存。

当多个线程同时执行lock.acquire()时,只有一个线程能成功地获取锁,然后继续执行代码,其他线程就继续等待直到获得锁为止。
获得锁的线程用完后一定要释放锁,否则那些苦苦等待锁的线程将永远等待下去,成为死线程。所以我们用try...finally来确保锁一定会被释放。
锁的好处就是确保了某段关键代码只能由一个线程从头到尾完整地执行,坏处当然也很多,首先是阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了。其次,由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁,导致多个线程全部挂起,既不能执行,也无法结束,只能靠操作系统强制终止。

import threading,time
def job1():
global A
for i in range(2):
print("get A_value of job1",A)
A+=1
print("A + 1 = %d"%(A))
time.sleep(1)
print("get A_value of job1",A)
def job2():
global A
for i in range(2):
print("get A_value of job2",A)
A+=10
print("A + 10 = %d"%(A))
time.sleep(3)
print("get A_value of job2",A)
if __name__== '__main__':
print("begin")
lock=threading.Lock()
A=0
t1=threading.Thread(target=job1)
t2=threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()
print("end")
'''输出:
begin
('get A_value of job1', 0)
A + 1 = 1
('get A_value of job2', 1)
A + 10 = 11
('get A_value of job1', 11)
A + 1 = 12
('get A_value of job1', 12)
('get A_value of job2', 12)
A + 10 = 22
('get A_value of job2', 22)
end
'''

无线程锁

import threading,time
def job1():
global A,lock
lock.acquire()
for i in range(2):
print("get A_value of job1",A)
A+=1
print("A + 1 = %d"%(A))
time.sleep(1)
print("get A_value of job1",A)
lock.release()
def job2():
global A,lock
lock.acquire()
for i in range(2):
print("get A_value of job2",A)
A+=10
print("A + 10 = %d"%(A))
time.sleep(3)
print("get A_value of job2",A)
lock.release()
if __name__== '__main__':
print("begin")
lock=threading.Lock()
A=0
t1=threading.Thread(target=job1)
t2=threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()
print("end")
'''输出:
begin
('get A_value of job1', 0)
A + 1 = 1
('get A_value of job1', 1)
A + 1 = 2
('get A_value of job1', 2)
('get A_value of job2', 2)
A + 10 = 12
('get A_value of job2', 12)
A + 10 = 22
('get A_value of job2', 22)
end
'''

有线程锁

7、死锁

死锁现象例子:共享资源A,B;锁lock1,lock2;两个线程threading1,threading2。

个人感觉就是锁中锁:

    一个线程threading1里一个锁lock1还没释放A资源(也就是lock1已锁定了A),就想获取另一个锁lock2来得到B资源(也就是想锁定B),所以在等待B资源释放;

    一个线程threading2里一个锁lock1还没释放B资源(也就是lock1已锁定了B),就想获取另一个锁lock2来得到A资源(也就是想锁定A),所以在等待A资源释放;

这样因两个线程相互等待资源释放就造成死锁。

#coding=utf-8
import threading,time
def job1():
global A,B,lock1,lock2
lock1.acquire()
for i in range(2):
print("获取job1中: A = %d"%(A))
A+=1
print("A + 1 = %d"%(A))
time.sleep(1)
print("获取job1中: A = %d"%(A))
lock2.acquire()
for i in range(2):
print("获取job1中: B = %d"%(B))
B+=10
print("B + 10 = %d"%(B))
time.sleep(3)
print("获取job1中: B = %d"%(B))
lock2.release()
lock1.release()
def job2():
global A,B,lock1,lock2
lock2.acquire()
for i in range(2):
print("获取job2中: B = %d"%(B))
B+=1
print("B + 10 = %d"%(B))
time.sleep(3)
print("获取job2中: B = %d"%(B))
lock1.acquire()
for i in range(2):
print("获取job1中: A = %d"%(A))
A+=10
print("A + 1 = %d"%(A))
time.sleep(1)
print("获取job1中: A = %d"%(A))
lock1.release()
lock2.release()
if __name__== '__main__':
print("begin")
lock1=threading.Lock()
lock2=threading.Lock()
A=B=0
t1=threading.Thread(target=job1)
t2=threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()
print("end")

死锁

小结:无论A是否等于B,lock1是否等于lock2,感觉只要存在锁中锁(每个线程里已acquire了还未释放又进行acquire)就会产生死锁。

8、递归锁:

RLock本身有一个计数器,如果碰到acquire,那么计数器+1;如果计数器大于0,那么其他线程无法查收,如果碰到release,计数器-1;直到如果计数器等于0,才会去执行下一个线程。
#coding=utf-8
import threading,time
def job1():
global A,B,lock1,lock2
lock1.acquire()
for i in range(2):
print("获取job1中: A = %d"%(A))
A+=1
print("A + 1 = %d"%(A))
time.sleep(1)
print("获取job1中: A = %d"%(A))
lock2.acquire()
for i in range(2):
print("获取job1中: B = %d"%(B))
B+=10
print("B + 10 = %d"%(B))
time.sleep(3)
print("获取job1中: B = %d"%(B))
lock2.release()
lock1.release()
def job2():
global A,B,lock1,lock2
lock2.acquire()
for i in range(2):
print("获取job2中: B = %d"%(B))
B+=1
print("B + 10 = %d"%(B))
time.sleep(3)
print("获取job2中: B = %d"%(B))
lock1.acquire()
for i in range(2):
print("获取job1中: A = %d"%(A))
A+=10
print("A + 1 = %d"%(A))
time.sleep(1)
print("获取job1中: A = %d"%(A))
lock1.release()
lock2.release()
if __name__== '__main__':
print("begin")
lock1=lock2=threading.RLock()
A=B=0
t1=threading.Thread(target=job1)
t2=threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()
print("end")
'''输出:
begin
获取job1中: A = 0
A + 1 = 1
获取job1中: A = 1
A + 1 = 2
获取job1中: A = 2
获取job1中: B = 0
B + 10 = 10
获取job1中: B = 10
B + 10 = 20
获取job1中: B = 20
获取job2中: B = 20
B + 10 = 21
获取job2中: B = 21
B + 10 = 22
获取job2中: B = 22
获取job1中: A = 2
A + 1 = 12
获取job1中: A = 12
A + 1 = 22
获取job1中: A = 22
end
'''

threading.Rlock()

每一个线程job里必须只有一个Rlock对象,有不同的Rlock对象也会产生死锁。如下:

#coding=utf-8
import threading,time
def job1():
global A,B,lock1,lock2
lock1.acquire()
for i in range(2):
print("获取job1中: A = %d"%(A))
A+=1
print("A + 1 = %d"%(A))
time.sleep(1)
print("获取job1中: A = %d"%(A))
lock2.acquire()
for i in range(2):
print("获取job1中: B = %d"%(B))
B+=10
print("B + 10 = %d"%(B))
time.sleep(3)
print("获取job1中: B = %d"%(B))
lock2.release()
lock1.release()
def job2():
global A,B,lock1,lock2
lock2.acquire()
for i in range(2):
print("获取job2中: B = %d"%(B))
B+=1
print("B + 10 = %d"%(B))
time.sleep(3)
print("获取job2中: B = %d"%(B))
lock1.acquire()
for i in range(2):
print("获取job1中: A = %d"%(A))
A+=10
print("A + 1 = %d"%(A))
time.sleep(1)
print("获取job1中: A = %d"%(A))
lock1.release()
lock2.release()
if __name__== '__main__':
print("begin")
lock1=threading.RLock()
lock2=threading.RLock()
A=B=0
t1=threading.Thread(target=job1)
t2=threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()
print("end")

9、GIL

GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念,是为了实现不同线程对共享资源访问的互斥,才引入了GIL。
在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势

多线程threading的更多相关文章

  1. python多线程threading.Lock锁用法实例

    本文实例讲述了python多线程threading.Lock锁的用法实例,分享给大家供大家参考.具体分析如下: python的锁可以独立提取出来 mutex = threading.Lock() #锁 ...

  2. Python初学——多线程Threading

    接着上篇继续跟着沫凡小哥学Python啦 1.1 什么是多线程 Threading 多线程可简单理解为同时执行多个任务. 多进程和多线程都可以执行多个任务,线程是进程的一部分.线程的特点是线程之间可以 ...

  3. 多线程-threading

    多线程-threading python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用 1. 使用threading模块 ...

  4. python的多线程threading

    多线程threading 1.Thread创建线程: 上代码: #!/usr/bin/env python3 import threading import time def A(): t_name ...

  5. 多进程 multiprocessing 多线程Threading 线程池和进程池concurrent.futures

    multiprocessing.procsess 定义一个函数 def func():pass 在if __name__=="__main__":中实例化 p = process( ...

  6. python中多进程multiprocessing、多线程threading、线程池threadpool

    浅显点理解:进程就是一个程序,里面的线程就是用来干活的,,,进程大,线程小 一.多线程threading 简单的单线程和多线程运行:一个参数时,后面要加逗号 步骤:for循环,相当于多个线程——t=t ...

  7. 物无定味适口者珍,Python3并发场景(CPU密集/IO密集)任务的并发方式的场景抉择(多线程threading/多进程multiprocessing/协程asyncio)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_221 一般情况下,大家对Python原生的并发/并行工作方式:进程.线程和协程的关系与区别都能讲清楚.甚至具体的对象名称.内置方法 ...

  8. python多线程threading

    本文通过 4个example 介绍python中多线程package —— threading的常用用法, 包括调用多线程, 同步队列类Queue, Ctrl+c结束多线程. example1. 调用 ...

  9. Python_多线程threading模块

    python 在执行的时候会淡定的在CPU上只允许一个线程运行,故Python在多核CPU的情况下也只能发挥出单核的功能,其中的原因:gil锁 gil 锁 (全局解释器锁):每个线程在执行时都需要先获 ...

随机推荐

  1. 分享几个常见的CMD命令,可能会用的上

    win7快捷命令.CMD命令secpol.msc(设置开机启动提示信息)services.msc(打开服务)dxdiag(检查DirectX信息)winver(检查Windows版本)regedit( ...

  2. 【Oracle学习笔记】定时任务(dbms_job)

    一.概述 Oralce中的任务有2种:Job和Dbms_job,两者的区别有: 1.  jobs是oracle数据库的对象, dbms_jobs只是jobs对象的一个实例, 就像对于tables, e ...

  3. mysql触发器new和old

    下面为您介绍mysql触发器new old的相关知识,供您参考学习,如果您在mysql触发器方面遇到过类似的问题,不妨一看,相信对您会有所帮助. mysql触发器new old: "NEW ...

  4. c#解决TCP“粘包”问题

    一:TCP粘包产生的原理 1,TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾.出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能 ...

  5. Web 性能优化:Preload与Prefetch的使用及在 Chrome 中的优先级

    摘要: 理解Preload与Prefetch. 原文:Web 性能优化:Preload,Prefetch的使用及在 Chrome 中的优先级 作者:前端小智 Fundebug经授权转载,版权归原作者所 ...

  6. 部署 apply plugin: 'realm-android'

    我在build.gradle中添加 apply plugin: 'realm-android' //依赖Realm数据库,插件化依赖  这个后,同步,清理,运行的时候报 应该在build.gradle ...

  7. mssql sqlserver 自动备份存储过程的方法分享

    转自:http://www.maomao365.com/?p=7847摘要: 为了更好的记录数据库中存储过程脚本的变化情况,下文采用数据库触发器来自动记载每次“存储过程”的变化(新增或修改),如下所示 ...

  8. 24G的SSD有什么用

    有台12G内存,带24G的SSD的笔记本,系统自带WINDOWS8,最近感觉很慢,就动手把1T的硬盘升级到512的SSD. BIOS里面明明看到24G的SSD,Windows里面就消失了(应该是坏掉了 ...

  9. mybatis常见错误

    1.传入单个参数为list时 List<Objects> query(@param("list") List<String> list) <selec ...

  10. 初窥css---盒子以及盒子扩展

    盒子以及盒子扩展 盒子 盒子是用来实现将网页区域化的一个非常重要的工具,盒子使得网页各部分十分清晰的被分开,对于程序员十分友好(...),并且使得网页更加容易维护. 盒子的常用属性 宽和高这两个属性就 ...