文章目录
前言
体能状态先于精神状态,习惯先于决心,聚焦先于喜好。
多线程的意义
最大的意义在于想尽办法发掘CPU的潜能——在IO和CPU性能差距巨大的情况下。
概念集合
进程和线程
进程是操作系统中的一个概念,是资源分配的最小单位;
线程是程序运行的最小单位,多个线程可以共享一个进程的资源;
进程的资源分配和回收代价都远大于线程;
尽管是线程,其资源的分配和回收也是需要消耗一定的时间和空间资源的。
同步(Synchronous)和异步(Asynchronous)
用于形容一次方法调用。
同步就是必须等待程序完全运行结束才能得到结果。
异步就是你调用完这个方法后可以立即去做别的事情,这个方法的运行将异步的进行——一般是另一个线程去进行。
临界区
临界区用于表示一种公共资源或者说共享数据。可以被多个线程使用,但是每一次只能有一个线程使用它。
线程的状态和转化
同步的重要属性
Java内存模型围绕三个特性:原子性,可见性和有序性
详情请看 Java 内存模型与8种基本操作、原子性、可见性、有序性
之一和二:原子操作和可见性
同步的两个重要特性是保持操作的原子性以及多个线程之间对临界区的可见性。
原子操作保证同一时间只有一个线程占用临界区并进行相关操作。
可见性用于保证,一个线程修改其占用的临界区资源时,比如一个变量,另一个线程可以立即感知到最新的变量值。
之三:有序性和指令重排
多线程之所以可以并发运行,是因为程序不总是需要占用CPU,这个时候处理器通过指令重排的方式,在不影响语义的前提下(这个规则其实很复杂),将可以提前运行的程序进行运行。
并发和并行
我们一般都说高并发,说明并发更为常见——因为在只有一个CPU的时候也可以通过多个线程交替进行的方式实现一起运行的效果。并发会涉及到线程的停顿和线程的切换——所以如果指令重排效率不高的话就不要用多线程。
至于并行,一般都会涉及到多个CPU,两个CPU分别独立的运行一个任务,两个任务都可以不停止的进行,这种多个任务同时在进行的方式被称为并行。
对象的发布和逸出
"发布"一个对象是指使对象可以在当前作用域之外的代码中使用。
对象的"逸出"是指,当这个对象不应该被发布,却被发布了,就被称为逸出。
发布对象好理解,对象逸出的例子:比如一个数组是final的,但是其可以保存多个元素(比如其他类型对象),该数据对外发布后,其内部元素被随之发布了——内部状态被发布——内部对象逸出。
线程安全:线程封闭
如果只在单线程内访问数据,就不需要同步——这是实现线程安全的最简单的方式之一,被称为线程封闭。
当某个对象封闭在一个线程中时,这种用法将自动实现线程安全性。
下面是是实现线程封闭的三种方式
Ad-hoc
完全由程序承担线程安全,一般而言就是我们程序员的事情了。
这种方式很脆弱,能不用就别用。
栈封闭
栈封闭中只能通过局部变量访问对象,由 JVM 的特性可知,在虚拟机栈中,每一个方法的运行都会伴随着一次入栈和出栈,栈帧中保存了局部变量表,这部分内容是线程私有的,故自然是线程封闭的。
简单说就是方法声明的变量自然而言是线程安全的。
ThreadLocal
维持线程封闭性的更规范的方法就是使用 ThreadLocal,ThreadLocal为指定对象提供get和set方法,每一个使用该变量的线程都存一个副本,从而防止对可变的单实例变量或全局变量进行共享。
或许有人说,我从新new一个对象不好吗,干嘛用副本——这就是ThradLocal的神奇之处——由它获得的对象是线程私有的,天然具备线程封闭的特性,新new的对象就需要考虑对象逸出的问题。
参考资料
[1]、https://www.cnblogs.com/zhehan54/p/6130030.html
[2]、https://blog.youkuaiyun.com/csxypr/article/details/95654381#commentBox
本文探讨了多线程的基本概念及其在计算机科学中的应用,包括进程与线程的区别、同步与异步的概念、临界区的管理、线程状态转换、Java内存模型的三大特性等,并介绍了实现线程安全的几种方法。
2987

被折叠的 条评论
为什么被折叠?



