什么是线程安全?线程安全是多线程编程中的一个重要概念。我们来看看维基百科是如何定义这个概念的:https://en.wikipedia.org/wiki/Thread_safety线程安全是一个适用于多线程代码的计算机编程概念。线程安全代码仅以确保所有线程正常运行并满足其设计规范而不会出现意外交互的方式操作共享数据结构。多线程代码一种计算机编程概念,可确保多个线程可以根据程序设计正确访问共享数据结构。或者更接近于编程语言的观点,线程安全是指至少有两个或多个线程操作同时共享数据区,并且其中至少有一个是写操作。如果还是想不通,可以去厕所观察一下,一个厕所是可以多人同时使用的。线程安全级别线程安全分为三个级别或粒度,如下:(1)线程安全在这种情况下,实际上不存在线程安全问题。比如上面的例子,每个人都有自己的专用厕所,所以不会出现竞争问题。(2)ConditionalsecurityConditionalsecurity,顾名思义,是有条件的。每个人共用几个厕所。抢资源者关上门,通过门隔离资源。后面的人在外面等着,直到里面的人出来。(3)不安全这种情况下没有门,资源安全性不能很好保证。所以,这种情况下,最好不要让多人同时直接使用。一般来说,有两种方法可以实现线程安全。首先,我们明白安全问题来自于竞争。没有竞争就没有问题。方法一:核心思想是避免共享数据结构和共享状态。包括:(1)使用线程局部变量(2)使用不可变对象方法二:核心思想是共享是必然的,需要保证条件。包括:(1)互斥锁(2)Java语言中的CAS原子操作实现策略这里以Java语言为例。上面提到的四种方法在Java中其实是支持的,对应的解决方案是:(1)ThreadLocal变量(2)不可变对象包括String、CopyOnWrite集合类(3)互斥锁包括JDK5之前synchronized的内置锁和LockJDK5以后的接口(四)J.U.C中以Atom开头的类,从Java中的处理可以看出策略还是很多的。当然,不同的策略其实都有特定的适用场景。另外,线程安全和同步方法的引入,会对代码的性能产生一定的影响,这点需要了解。一般来说,避免共享数据结构可以更优雅地解决并发问题。这种程序对多线程比较友好,性能也比较高。比如单机的ThreadLocal和分布式的Ator模型。这里没有竞争。第二个是不可变变量。多线程的操作都是CopyOnWrite,这也是为什么Scala等一些动态编程语言中的默认数据结构大部分都是不可变的。Immutability具有不可变的优点,但其缺点也很明显。如果需要频繁修改数据,会创建很多临时对象,占用更多内存。以上两种场景一般称为无锁实现,性能非常好。如果无法避免共享数据,那么CAS等原子操作的性能会更好。这种情况,我们一般称之为无锁,但实际上是利用操作系统的原子指令来实现的。在竞争不激烈的场景下表现比较好,通用的编程语言都有封装的工具类。如果竞争激烈,性能可能不会比使用互斥量高。互斥锁一般称为重量级锁,需要OS介入线程调度,适合在竞争激烈的场景下使用。这样,线程上下文的交换会降低系统的性能,所以在使用时要小心。线程并发技能图多线程编程领域其实涉及到很多计算机知识,线程安全只是冰山一角。作为一名技术人员,我们必须系统地学习并突破并发编程。很多人认为并发编程很难,其实是我没有掌握系统的学习方法。在这里放出一张我以前的并发知识图谱,供大家参考学习:查看原图进行总结。本文主要介绍什么是线程安全,以及实现线程安全的一些方法,结合Java语言对相关知识进行说明,最后总结出Java并发学习的知识图谱。只要了解并掌握其中的所有内容,就可以在多线程领域从青铜晋级为王者,但是学习之路,学无止境,不能急功近利,一定要抓好基础,然后一步一个脚印,一步一个脚印,慢一点也没关系,坚持下去,一定会有收获的。
