从找对象到多线程

简介:

最近遇到了一个和多线程有关的事,顺便简单复习了下相关概念,稍后举个栗子🌰来解释下。

进程 and 线程

进程我们都知道,就是应用程序的启动实例。比如我们运行一个游戏,打开一个软件,就是开启了一个进程。

而线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。

我们可以简单的理解:为了做一件事,我开了一个进程,为了让这件事更有效率的完成,我开了多个线程。

### 从找对象入手加深理解

如果这么说还是不清楚的话,我们以一个找对象的例子来加深理解:

​ 读研了,望着身边的小伙伴一个个都是成双成对,笔者有一个万年单身的好基友就跟一条酸菜鱼似的(又酸又菜又多余),想着要不也找个女朋友吧?于是就创建了一个名为 「找对象」的进程。但是学校女生太多了,如果一个一个试的话不知道啥时候才能脱单。这时候,万能的度娘给出了建议,为什么不同时下手呢?

于是,他就创建了两个「撩妹」的线程,每个线程负责撩一个妹子。但这时就有问题出来了。

​ 虽然他可以同时撩两个妹子,但是有些事情就是没办法同时和两个妹子做,比如上课、吃饭、散步。这个时候就需要 「数据保护」。做这些事情的时候,他一次只能跟一个妹子做,这就叫做 「临界区」。他撩的两个妹子,一个是红玫瑰,一个是白玫瑰,各有各的特点,这是她们的 「私有属性」。这两个妹子都可以跟他约会,此时他就是一个 「共享内存」。如果某一天他跟其中一个妹子在外面约会,那另一个撩妹线程就只能 「阻塞」 了。但是为了防止后院起火,不让另一个妹子不爽,他就只能发条朋友圈说自己在学习,不想被打扰,这就叫 「互斥锁」。同时为了不让她们影响对方的存在,他用QQ叫着其中一个的小名,微信却是另一个的情侣头像,这就是「消息传递」

​ 上述两个线程在某种意义上就构成了 「竞态条件」(个人认为叫做「竞争状态」会更好)。如果他只有这两个线程的话,想要完成「找对象」这个进程,就只能看这两个线程谁的执行效率更高(其实就是看谁先运行完) 了。这么一看,我的好基友貌似很快就可以完成「找对象」这一进程了,因为无论是哪个线程,只要有一个「撩妹」线程结束了,整个进程也就结束了。

​ 但是在结束前可能会出现一些问题(注意这里是可能),如果他在排约会档期时一旦没有进行良好的调度,就很有可能会出现两个妹子约在同一天约会,基友却没办法到达的情况,这种情况就叫 「死锁」,即较长时间的等待或资源竞争。亦或是如果不幸被两个妹子都发觉了对方的存在,却又为表大度,你让我我让你,最终导致「找对象」进程无法进行下去,这就叫做 「活锁」。 如果此时出现了一个 「工具人」 妹子,主动倒追我基友,这样的话即使被加入了「找对象」的进程,也可能会因为一系列问题始终没法和他单独约会(毕竟还有两个「撩妹」线程在进行着),这种情况就叫做 「饥饿」。 这三种情况总结一下就是:

  1. 死锁:争来争去 谁也得不到
  2. 活锁:让来让去 谁都不拥有
  3. 饥饿:排多久 都轮不到自己

倘若我基友最后撩成功的女朋友并不是他最喜欢的那个人,即最终的运行结果和预期不同,这就叫 「线程不安全」。反之,如果最后撩成功的妹子是他最喜欢的,即最终的结果和预期相同,那这个就叫 「线程安全」

这么一看,真是人生如戏。只是可悲的是,我本以为现在执行的是一个单进程,却没想到也只是别人的一个线程罢了。

相关文章
|
6月前
|
存储 设计模式 安全
Java 编程问题:十、并发-线程池、可调用对象和同步器2
Java 编程问题:十、并发-线程池、可调用对象和同步器
59 0
|
6月前
|
缓存 安全 Java
Java 编程问题:十、并发-线程池、可调用对象和同步器1
Java 编程问题:十、并发-线程池、可调用对象和同步器
64 0
|
6月前
|
数据处理
多线程与并发编程【线程对象锁、死锁及解决方案、线程并发协作、生产者与消费者模式】(四)-全面详解(学习总结---从入门到深化)
多线程与并发编程【线程对象锁、死锁及解决方案、线程并发协作、生产者与消费者模式】(四)-全面详解(学习总结---从入门到深化)
67 1
|
2月前
|
存储 Java 程序员
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。
|
2月前
|
安全 Java
LinkedBlockingQueue 是线程安全的,为什么会有两个线程都take()到同一个对象了?
LinkedBlockingQueue 是线程安全的,为什么会有两个线程都take()到同一个对象了?
44 0
|
3月前
|
安全 Java C#
Spring创建的单例对象,存在线程安全问题吗?
Spring框架提供了多种Bean作用域,包括单例(Singleton)、原型(Prototype)、请求(Request)、会话(Session)、全局会话(GlobalSession)等。单例是默认作用域,保证每个Spring容器中只有一个Bean实例;原型作用域则每次请求都会创建一个新的Bean实例;请求和会话作用域分别与HTTP请求和会话绑定,在Web应用中有效。 单例Bean在多线程环境中可能面临线程安全问题,Spring容器虽然确保Bean的创建过程是线程安全的,但Bean的使用安全性需开发者自行保证。保持Bean无状态是最简单的线程安全策略;
|
4月前
|
存储 缓存 算法
同时使用线程本地变量以及对象缓存的问题
【7月更文挑战第15天】同时使用线程本地变量和对象缓存需小心处理以避免数据不一致、竞争条件及内存泄漏等问题。线程本地变量使各线程拥有独立存储,但若与对象缓存关联,可能导致多线程环境下访问旧数据。缺乏同步机制时,多线程并发修改缓存中的共享对象还会引起数据混乱。此外,若线程结束时未释放对象引用,可能导致内存泄漏。例如,在Web服务器场景下,若一更新缓存而另一线程仍获取旧数据,则可能返回错误信息;在图像处理应用中,若多线程无序修改算法对象则可能产生错误处理结果。因此,需确保数据一致性、避免竞争条件并妥善管理内存。
|
4月前
|
设计模式 存储 缓存
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
55 0
|
5月前
|
安全 Java
如何测试map对象的线程不安全
【6月更文挑战第20天】如何测试map对象的线程不安全
41 0
|
6月前
|
存储 安全 Java
调用链跨线程传递 ThreadLocal 对象对比
说起本地线程专属变量,大家首先会想到的是 JDK 默认提供的 ThreadLocal,用来存储在整个链路中都需要访问的数据,并且是线程安全的。由于在落地全链路压测的过程中,一个基本并核心的功能需求是流量标记需要在整个链路中进行传递,那么线程上下文环境成为解决这个问题最合适的技术。
81 2
调用链跨线程传递 ThreadLocal 对象对比