第三十三天- 线程创建、join、守护线程、死锁
1.线程,线程创建
概念:在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程,线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程,车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线。流水线的工作需要电源,电源就相当于cpu。
所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。
多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。
创建:
线程创建方式一:
from multiprocessing import Process
from threading import Thread def func(n):
print('xxxxx')
print('>>>',n) if __name__ == '__main__': # p = Process(target=func,args=(1,))
# p.start() t = Thread(target=func,args=(1,)) # 直接创建
t.start() print('主线程结束')
面向对象创建:
from threading import Thread # 面向对象创建
class Mythread(Thread): # 继承Thread父类 def __init__(self,xx):
super().__init__()
self.xx = xx def run(self): # 必须有run,覆盖父类run中的pass
print(self.xx)
print('我重置父类方法') def func1(self): # 写其他方法
print('我是func1') if __name__ == '__main__': t1 = Mythread('xx')
t1.start() # 默认执行run
t1.func1() # 调用其他方法
# from multiprocessing import Process
from threading import Thread
2.Thread类方法
join方法:
主线程等待join子线程执行完毕后才执行
import time
from threading import Thread def func(n):
time.sleep(n)
print('我是子线程') if __name__ == '__main__': t = Thread(target=func,args=(1,))
t.start() t.join() # 等待子线程执行结束
print('我是主线程,子线程结束再执行我')
join
其他方法:
''
Thread实例对象的方法
# isAlive(): 返回线程是否活动的。
# getName(): 返回线程名。
# setName(): 设置线程名。 threading模块提供的一些方法:
# threading.currentThread(): 返回当前的线程变量。
# threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
# threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
'''
import time, threading
from threading import Thread, current_thread def func():
time.sleep(2)
print('子线程,名字是:', current_thread().getName()) # 返回线程名
print('子线程,ID是:', current_thread().ident) # 返回线程id if __name__ == '__main__': for i in range(10):
t = Thread(target=func, )
t.start() print(threading.enumerate()) # 返回一个包含正在运行的list
print(threading.activeCount()) # 返回正在运行的线程数量,等同len(threading.enumerate()) print('主线程结束')
其他方法示例
3.守护线程、事件
守护线程:
主进程结束,守护进程跟着结束,再执行非守护进程
主线程要等待所有非守护线程运行结束才会结束(因为他们属于同一进程)
需注意:运行结束并非终止运行
xxx.setDaemon(True) 或者 xxx.daemon = True
import time
from threading import Thread
from multiprocessing import Process def func1():
time.sleep(3)
print('任务1结束') def func2():
time.sleep(2)
print('任务2结束') if __name__ == '__main__': # p1 = Process(target=func1,)
# p2 = Process(target=func2,)
# # p1.daemon = True
# p2.daemon = True
# p1.start()
# p2.start()
#
# print('主进程结束') t1 = Thread(target=func1,)
t2 = Thread(target=func2,)
# t1.setDaemon(True) # 只打印出 主线程和t2 因为t2时间比t1小
t2.setDaemon(True) # 会正常打印出所有 因为t1时间大于t2
t1.start()
t2.start() print('主线程结束')
守护线程与守护进程
事件:
event.isSet():返回event的状态值;
event.wait():如果 event.isSet()==False将阻塞线程;
event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
event.clear():恢复event的状态值为False。
import time
from threading import Event e = Event() # 默认false状态
print(e.isSet()) # 事件当前状态 e.set() # 改变成Ture
print(e.isSet()) print('稍等...')
# e.clear() # 将e的状态改为False
e.wait() # 如果 event.isSet()==False将阻塞线程 if e.isSet() == True:
time.sleep(1)
print('滴滴滴,上车吧...')
事件代码示例
4.线程间数据问题
开启一个线程所需要的时间要远小于开启一个进程
import time
from multiprocessing import Process
from threading import Thread def func(i):
return '我是任务%s'%i if __name__ == '__main__': # 多线程
t_list = []
t_start_time = time.time()
for i in range(10):
t = Thread(target=func,args=(i,))
t_list.append(t)
t.start() [tt.join() for tt in t_list]
t_end_time = time.time()
t_dif_time = t_end_time - t_start_time # 多进程
p_list = []
p_start_time = time.time()
for i in range(10):
p = Process(target=func,args=(i,))
p_list.append(p)
p.start() [pp.join() for pp in p_list]
p_end_time = time.time()
p_dif_time = p_end_time - p_start_time
# 结果受cpu影响 print('多线程耗时:',t_dif_time)
print('多进程耗时:',p_dif_time)
print('主线程结束') '''
多线程耗时: 0.0020008087158203125
多进程耗时: 0.4188823699951172
'''
多线程和多进程效率对比
线程之间共享进程资源(全局变量在多个线程之间共享),但也会导致数据不但全问题
import time
from threading import Thread num = 100 def func():
global num
tep = num # tep替换 模拟多步操作
time.sleep(0.001) # 模拟延迟
tep -= 1
num = tep if __name__ == '__main__': t_list = []
for i in range(100):
t = Thread(target=func,)
t_list.append(t)
t.start() [tt.join() for tt in t_list] print('主线程的num',num) # 打印出不是100可知数据是共享的 # 理论上应该是0,但多线程是并发执行的,会出现上一个线程还在运算中时,下一个线程并未等待它返回值
# 也拿了原来的值进来运算,所以打印出了91,92,93不等,可知多线程数据是不安全的
'''
主线程的num 92
'''
验证多线程之间数据共享 数据不安全问题
加锁解决多线程数据不安全问题
import time
from threading import Thread,Lock num = 100
def func(lock,i):
global num
lock.acquire() # 加锁 tep = num
time.sleep(0.001) # 模拟延迟
tep -= 1
num = tep lock.release() # 释放 if __name__ == '__main__':
t_list = []
lock = Lock()
for i in range(100):
t = Thread(target=func,args=(lock,i))
t_list.append(t)
t.start() [tt.join() for tt in t_list]
print('主线程num',num) '''
主线程num 0
'''
Lock
信号量Semaphore
import time,random
from threading import Thread,Semaphore def func(i,s):
s.acquire()
print('%s张烧饼'%i)
time.sleep(random.randint(1,3))
s.release()
# 出来一个进去一个 始终6个 最后不足6个就都进来了 if __name__ == '__main__':
s = Semaphore(6) # 与Lock类似,不过可限制最大连接数,如这里同时只有6个线程可以获得semaphore
for i in range(28):
t = Thread(target=func,args=(i,s,))
t.start()
Semaphore
5.死锁和递归锁
死锁现象:有多个锁时,双方互相等待对方释放对方手里拿到的那个锁导致死锁

import time
from threading import Thread,Lock def func1(lock_A,lock_B):
lock_A.acquire()
print('张全蛋拿到了A锁')
time.sleep(0.5)
lock_B.acquire()
print('张全蛋拿到了B锁')
lock_B.release()
lock_A.release() def func2(lock_A,lock_B):
lock_B.acquire()
print('赵二狗拿到了B锁')
lock_A.acquire()
print('赵二狗拿到了A锁')
lock_A.release()
lock_B.release() if __name__ == '__main__': lock_A = Lock()
lock_B = Lock()
t1 = Thread(target=func1,args=(lock_A,lock_B,))
t2 = Thread(target=func2,args=(lock_A,lock_B,))
t1.start()
t2.start()
死锁现象
递归锁:RLock
RLock管理一个内置的计数器,
每当调用acquire()时内置计数器-1;
调用release() 时内置计数器+1;
计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。

# 递归锁解决死锁现象
import time
from threading import Thread,Lock,RLock def func1(lock_A,lock_B):
lock_A.acquire()
print('张全蛋拿到了A锁')
time.sleep(0.5)
lock_B.acquire()
print('张全蛋拿到了B锁')
lock_B.release()
lock_A.release() def func2(lock_A,lock_B):
lock_B.acquire()
print('赵二狗拿到了B锁')
lock_A.acquire()
print('赵二狗拿到了A锁')
lock_A.release()
lock_B.release() if __name__ == '__main__': # lock_A = Lock()
# lock_B = Lock()
lock_A = lock_B = RLock()
t1 = Thread(target=func1,args=(lock_A,lock_B,))
t2 = Thread(target=func2,args=(lock_A,lock_B,))
t1.start()
t2.start()
递归锁解决死锁现象
第三十三天- 线程创建、join、守护线程、死锁的更多相关文章
- 线程 Thread Runnable 守护线程 join MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量
Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程: 1.线程是一堆指令,是操作系统调度 ...
- Java多线程系列--“基础篇”10之 线程优先级和守护线程
概要 本章,会对守护线程和线程优先级进行介绍.涉及到的内容包括:1. 线程优先级的介绍2. 线程优先级的示例3. 守护线程的示例 转载请注明出处:http://www.cnblogs.com/skyw ...
- Java多线程(十)——线程优先级和守护线程
一.线程优先级的介绍 java 中的线程优先级的范围是1-10,默认的优先级是5.“高优先级线程”会优先于“低优先级线程”执行. java 中有两种线程:用户线程和守护线程.可以通过isDaemon( ...
- Java 多线程基础(十一)线程优先级和守护线程
Java 多线程基础(十一)线程优先级和守护线程 一.线程优先级 Java 提供了一个线程调度器来监控程序启动后进去就绪状态的所有线程.线程调度器通过线程的优先级来决定调度哪些线程执行.一般来说,Ja ...
- java的守护线程与非守护线程
最近重新研究Java基础知识,发现以前太多知识知识略略带过了,比较说Java的线程机制,在Java中有两类线程:User Thread(用户线程).Daemon Thread(守护线程) ,(PS:以 ...
- Java中的守护线程和非守护线程(转载)
<什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...
- Java - 线程优先级和守护线程
Java多线程系列--“基础篇”10之 线程优先级和守护线程 概要 本章,会对守护线程和线程优先级进行介绍.涉及到的内容包括:1. 线程优先级的介绍2. 线程优先级的示例3. 守护线程的示例 转载请注 ...
- java 多线程之 线程优先级和守护线程
线程优先级的介绍 java 中的线程优先级的范围是1-10,默认的优先级是5."高优先级线程"会优先于"低优先级线程"执行. java 中有两种线程:用户线程和 ...
- [Java基础] java的守护线程与非守护线程
最近重新研究Java基础知识,发现以前太多知识知识略略带过了,比较说Java的线程机制,在Java中有两类线程:User Thread(用户线程).Daemon Thread(守护线程) ,(PS:以 ...
随机推荐
- zabbix 监控安装
注意:此篇是在安装好lnmp环境后才能部署的操作,所以,做之前准备好lnmp环境,或者可以参考我做的lnmp环境,之后接着此篇开始安装 监控系统Zabbix-3.2.1的安装 zabbix-serve ...
- Liferay开发实战(2):Service Builder生成持久化层,及开发服务层
本文Liferay适用版本:v6.2.ce-ga6版 Liferay的插件体系是:模型-视图-控制器的portlet MVC框架.MVC是一个伟大的用于Web应用程序的设计模式,在实际应用中还应处理持 ...
- Celery -- 分布式任务队列 及实例
Celery 使用场景及实例 Celery介绍和基本使用 在项目中如何使用celery 启用多个workers Celery 定时任务 与django结合 通过django配置celery perio ...
- 基于GTK+3 开发远程控制管理软件(C语言实现)系列二 Centos7下开发环境搭建
一.安装gcc gcc-c++ make等编译工具 yum install gcc gcc-c++ kernel-devel 这一步,其实可以不用做,你在安装Centos7的时候,如果选择开发模式安装 ...
- 面试基础知识集合(python、计算机网络、操作系统、数据结构、数据库等杂记)
python python _.__.__xx__之间的差别 python中range.xrange和randrange的区别 python中 =.copy.deepcopy的差别 python 继承 ...
- SQLServer中的cross apply和FOR XML PATH
参考: FOR XML PATH:http://www.cnblogs.com/doubleliang/archive/2011/07/06/2098775.html cross apply:http ...
- 轻量级web富文本框——wangEditor使用手册(1)——基本应用 demo
最新版wangEditor: 配置说明:http://www.wangeditor.com/doc.html demo演示:http://www.wangeditor.com/wangEditor/d ...
- spring boot 与 thymeleaf (1): 国际化
在thymeleaf 里面有个消息表达式: #{...} , 可以借此来实现国际化. 在我使用这个功能的时候, 碰到了一个问题, 按照 JavaEE开发的颠覆者 Spring Boot实战 上面编码 ...
- 【转载】Layered Window(分层窗体,透明窗体)
本文转载自花间醉卧<Layered Window(分层窗体,透明窗体)> //为窗体添加WS_EX_LAYERED属性,该属性使窗体支持透明 ModifyStyleEx(0, WS_EX_ ...
- Flux --> Redux --> Redux React 基础实例教程
本文的目的很简单,介绍Redux相关概念用法 及其在React项目中的基本使用 假设你会一些ES6.会一些React.有看过Redux相关的文章,这篇入门小文应该能帮助你理一下相关的知识 一般来说,推 ...