第二十九章:初识线程

什么是线程

线程是操作系统最小的运算调度单位,被包含在进程中,一个线程就是一个固定的 执行流程

线程的进程的关系  重点

线程不能单独存在 必须存在于进程中,

进程是一个资源单位,其包含了运行程序所需的所有资源

线程才是真正的执行单位

没有线程,进程中的资源无法被利用起来,所以一个进程至少包含一个线程,称之为主线程

当我们启动一个程序时,操作系统就会自己为这个程序创建一个主线程

线程可以由程序后期开启  ,自己开启线程称之为子线程

为什么需要线程   重点

目的只有一个就是提高效率

就像一个车间 如果产量更不上 就在造一条流水线

当然可以再造一个新车间,那需要把原材料运过去  ,这个过程是非常耗时的

所以通常情况是创建新的流水线 而不是车间  即 线程

如何使用   重点

使用方法和多进程一模一样

不过开启线程的代码可以放在任何位置  开启进程必须放在判断下面

from threading import Thread,current_threadimport time?def task():    print("2",current_thread())    print("子线程running")    time.sleep(10)    print("子线程over")?# 使用方法一  直接实例化Thread类if __name__ == ‘__main__‘:    t = Thread(target=task)    t.start()        # task()    # 执行顺序不固定 如果开启线程速度足够快  可能子线程先执行    print("主线程over")    print("1",current_thread())?# 使用方法二 继承Thread 覆盖run方法class MyThread(Thread):    def run(self):        print("子线程run!")m = MyThread()print("主线over")?# 使用方法和多进程一模一样   开启线程的代码可以放在任何位置  开启进程必须放在判断下面

线程的特点  重点

1.创建开销小

2.同一个进程中的多个线程数据时共享的

3.多个线程之间,是平等的没有父子关系    所有线程的PID都是相同的

# 创建线程开销对比import osfrom threading import  Threadfrom multiprocessing import Process?import time??def task():    # print("hello")    print(os.getpid())    pass?if __name__ == ‘__main__‘:?    st_time = time.time()?    ts = []    for i in range(100):        t = Thread(target=task)        # t = Process(target=task)        t.start()        ts.append(t)?    for t in ts:        t.join()?    print(time.time()-st_time)    print("主over")

守护线程  了解

一个线程可以设置为另一个线程的守护线程

特点:  被守护线程结束后守护线程也随之结束

# 守护线程会等到所有非守护线程结束后结束  !    前提是除了主线程之外 还有后别的非守护# 当然如果守护线程已经完成任务 立马就结束了
from threading import Threadimport time?def task():    print("子1running......")    time.sleep(100)    print("子1over......")?def task2():    print("子2running......")    time.sleep(4)    print("子2over......")    t = Thread(target=task)t.daemon = Truet.start()?t2 =Thread(target=task2)t2.start()?print("主over")

线程 互斥锁

共享意味着竞争

线程中也存在安全问题,

多线程可以并发执行,一旦并发了并且访问了同一个资源就会有问题

解决方案:还是互斥锁

案例:

from threading import Thread,enumerate,Lockimport time?number = 10?lock = Lock()?def task():    global number    lock.acquire()    a = number    time.sleep(0.1)    number = a - 1    lock.release()?for i in range(10):    t = Thread(target=task)    t.start()?for t in enumerate()[1:]:    # print(t)    t.join()    print(number)

死锁问题

from threading import Lock, current_thread, Thread?"""    死锁问题    当程序出现了不止一把锁,分别被不同的线程持有, 有一个资源 要想使用必须同时具备两把锁    这时候程序就会进程无限卡死状态 ,这就称之为死锁    例如:        要吃饭 必须具备盘子和筷子   但是一个人拿着盘子 等筷子  另一个人拿着筷子等盘子        如何避免死锁问题          锁不要有多个,一个足够        如果真的发生了死锁问题,必须迫使一方先交出锁        """import time# 盘子lock1 = Lock()?# 筷子lock2 = Lock()?def eat1():    lock1.acquire()    print("%s抢到了盘子" % current_thread().name)    time.sleep(0.5)    lock2.acquire()    print("%s抢到了筷子" % current_thread().name)?    print("%s开吃了!" % current_thread().name)    lock2.release()    print("%s放下筷子" % current_thread().name)?    lock1.release()    print("%s放下盘子" % current_thread().name)??def eat2():    lock2.acquire()    print("%s抢到了筷子" % current_thread().name)?    lock1.acquire()    print("%s抢到了盘子" % current_thread().name)??    print("%s开吃了!" % current_thread().name)??    lock1.release()    print("%s放下盘子" % current_thread().name)    lock2.release()    print("%s放下筷子" % current_thread().name)??t1 = Thread(target=eat1)??t2 = Thread(target=eat2)?t1.start()t2.start()

可重入锁   了解

Rlock  称之为递归锁或者可重入锁

Rlock不是用来解决死锁问题的

与Lock唯一的区别:
Rlock同一线程可以多次执行acquire 但是执行几次acquire就应该对应release几次
   
如果一个线程已经执行过acquire 其他线程将无法执行acquire

?from threading import RLock, Lock, Thread?# l = Lock()## l.acquire()# print("1")# l.acquire()# print("2")??l = RLock()?# l.acquire()# print("1")# l.acquire()# print("2")?def task():    l.acquire()    print("子run......")    l.release()??# 主线程锁了一次l.acquire()l.acquire()?l.release()l.release()t1 = Thread(target=task)t1.start()

信号量  了解

?""" 信号量 了解Lock  RLock?可以现在被锁定的代码 同时可以被多少线程并发访问Lock 锁住一个马桶  同时只能有一个Semaphore 锁住一个公共厕所    同时可以来一堆人??用途: 仅用于控制并发访问   并不能防止并发修改造成的问题"""?from threading import Semaphore, Threadimport time?s = Semaphore(5)def task():    s.acquire()    print("子run")    time.sleep(3)    print("子over")    s.release()?for i in range(10):    t = Thread(target=task)    t.start()

回顾

多线程

线程是CPU的最小执行单位, 线程本质是一堆代码构成的执行流程

线程被包含在进程中,

进程是一个资源单位,其中存储着该程序运行所需所有资源, 可以比喻为一个车间

线程就是车间中国一条流水线,上面放的是制作产品的具体方法(就是的代码)

一个进程至少有一个线程,操作系统在运行一个程序时 会在进程中自动开启一条线程

一个进程中可以有多个线程

同一个进程中的线程共享进程内的数据

创建线程速度非常快 开销小

线程之间没有父子关系    都是平等的

使用方式和进程一致

学习多线程  多进程 都是为了提高效率 ,通过并发执行多个任务

实现并发的方式,多线程和多进程

原文地址:https://www.cnblogs.com/haojunliancheng/p/10975357.html

时间: 2024-10-11 03:54:48

第二十九章:初识线程的相关文章

Gradle 1.12用户指南翻译——第二十九章. Checkstyle 插件

其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc/tree/1.12. 直接浏览双语版的文档请访问: http://gradledoc.qiniudn.com/1.12/userguide/userguide.html. 另外,Android 手机用户可通过我写的一个程序浏览文档,带缓存功能的,目前

【WPF学习】第二十九章 元素绑定——将元素绑定到一起

原文:[WPF学习]第二十九章 元素绑定--将元素绑定到一起 数据banding的最简单情形是,源对象时WPF元素而且源属性是依赖性属性.前面章节解释过,依赖项属性具有内置的更改通知支持.因此,当在源对象中改变依赖项属性的值时,会立即更新目标对象中的绑定属性.这正是我们所需要的行为--而且不必为此构建任何额外的基础结构. 为理解如何将一个元素绑定到另一个元素,下面创建一个简单的示例.该示例窗口包含了两个控件:一个Slider控件和一个具有单行文本的TextBlock控件.如果向右拖动滑动条上的滑

第二十九章 springboot + zipkin + mysql

zipkin的数据存储可以存在4个地方: 内存(仅用于测试,数据不会持久化,zipkin-server关掉,数据就没有了) 这也是之前使用的 mysql 可能是最熟悉的方式 es Cassandra 一.代码(基于 第二十八章 springboot + zipkin(brave定制-AsyncHttpClient)) 1.pom.xml 1 <dependency> 2 <groupId>io.zipkin.brave</groupId> 3 <artifactI

奋斗吧,程序员——第二十九章 伤心桥下春波绿,疑是惊鸿照影来

手机对我们的开发板按下红外发送键,很快一张图片从屏幕上显示出来,大功告成! 虽然代码还不能发布,但是看到成果的那一刻,内心还是非常激动的. 证明现在的我已非吴下阿蒙. 可惜没人和我分享胜利的喜悦,现在已是深夜. 最近一段时间,陈曦出差跑业务去了. 我打了个哈欠,终于可以美美的睡一觉了. 记得刚开始写代码的时候,有一次我的代码把系统搞死了,嘉庆看了一眼,云淡风轻地在代码里加了个sleep(1)解决问题,我才明白原来睡眠是这么重要的事情. 不光线程要睡觉,人更要睡觉. 因为太晚了,我决定不回家,直接

我的学习之路_第二十九章_bootstrap

bootstrap 内置了html,css,js插件为一体的前端框架 响应式布局: 设计一套页面就可以使用于很多现实设备 bootstrap: 1.入门(响应式布局的容器) 1.先进入jQuery的js2.再引入bootstrap的js3.引入bootstrap的css文件4.设置视口(支持移动设备优先) <meta name="viewport" content="width=device-width,initial-scale=1"> 5.页面创建一

第二十九章 集成

集成是指一种软件开发行为:将一些独立的软件组合为一个完整系统. 集成方式的重要性 从周到的继承中,你能预期获得某些下列的益处: 更容易诊断缺陷: 缺陷更少: 脚手架更少: 花费更少的时间获得第一个能工作的产品: 更短的整体开发进度表: 更好的顾客关系: 增强士气: 增加项目完成的机会: 更可靠地估计进度表: 更准确的现状报告: 改善代码的质量: 较少的文档. 集成频率--阶段式集成还是增量集成 阶段式集成 它遵循下列明确的步骤: 设计.编码.测试.调试各个类.这一步称为单元开发: 将这些类组合为

第二十九章:数据库维护

@author: Tobin @date: 2019/11/7 18:03:17 数据库维护. ANALYZE TABLE orders; CHECK TABLE orders, orderitems; 诊断启动问题. 查看日志文件. 原文地址:https://www.cnblogs.com/zuotongbin/p/11814196.html

“全栈2019”Java多线程第二十五章:生产者与消费者线程详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第二十五章:生产者与消费者线程详解 下一章 "全栈2019"Java多线程第二十六章:同步方法生产者与消费者线程 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"

“全栈2019”Java多线程第二十六章:同步方法生产者与消费者线程

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第二十六章:同步方法生产者与消费者线程 下一章 "全栈2019"Java多线程第二十七章:Lock获取lock/释放unlock锁 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorha