Java并发编程那些事儿(三)——ThreadLocal及原子性与可见性

栏目: IT技术 · 发布时间: 3年前

内容简介:原创:花括号MC(微信公众号:huakuohao-mc)。关注JAVA基础编程及大数据,注重经验分享及个人成长。点一下你会更好看耶

原创:花括号MC(微信公众号:huakuohao-mc)。关注 JAVA 基础编程及大数据,注重经验分享及个人成长。

这是并发编程系列的第三篇文章。 上一篇 介绍的是线程间通过锁同步的方式实现共享资源的安全访问,这篇讲一下如何通过不加锁的方式实现共享可变资源的访问。

ThreadLocal介绍

上篇文章讲到,如果想在多线程的环境下,实现共享可变资源的安全访问,最好的方式是加锁,也就是同一时刻只有一个线程在使用共享可变资源。如果我们有一种方式可以根除对变量的共享,那么就可以实现不加锁的情况下对变量进行安全访问。

还拿之前抢卫生间坑位的例子举例,如果只有一个卫生间坑位,五个人都想去卫生间的话,那么就需要加锁同步。如果给每个人都提供一个单独的坑位,那么就可以不加锁了,因为没有争抢的场景发生。

Java 通过 ThreadLocal 来实现每个线程都拥有一份自己的共享变量的拷贝。大家可以把 ThreadLocal<T> 简单的理解成 Map<Thread,T>ThreadLocal 提供了 getset 等方法, get 方法总是返回当前线程调用 set 方法时设置的最新值。如果是第一次调用 get 方法,将会返回 initialValue 方法里面的设置的初始值。

ThreadLocal使用场景

ThreadLocal 通常用在防止全局变量的共享,或者单例实例的共享。举个例子,连接数据库的时候,首先要创建一个 connection 连接对象,但是这个 connection 对象不一定是线程安全的,如果所有线程方法都使用这个对象,进行数据库的连接,就有可能会出问题。如果使用加锁进行同步,那么性能上会有问题,这个时候就可以通过 ThreadLocal 来帮忙,让每个线程都持有一份 connection 对象。这样就可以完美解决问题。

各位一定要注意 ThreadLocal 的使用场景,千万不要乱用。

原子性和可见性

在使用加锁同步的方式来保证共享资源实现安全访问的方案中,锁除了保证资源的原子性以外还对可见性做了保证。

原子性:并发编程里面的原子性,与数据库里面的原子性概念是一致,都是表示操作时不可分割的,必须在不打断的情况下,一次执行完成。

可见性:在单线程的情况下,一个变量被修改之后,当再次需要使用的时候,肯定会读取到正确的值,但是在多线程情况下,一个线程修改变量之后,其他线程并不能保证第一时间读到这个变量。

如果要理解这个问题,需要对 JVM 的重 排序 有一定的理解。所谓的重排序就是编译器会对你写的代码进行顺序调整,以达到优化运行效率的目的。

对于可见性问题,可以通过如下代码示例进行说明

这段会启动一个读线程,当 readytrue 时会打印出 number 的值。然后主线程会修改 readynumber 的值。如果该段代码是在 client 模式下运行,你很可能会看到正确的结果 34 ,但是如果在是 server 模式下运行,那么程序可能进入死循环,因为读线程看不到主线程对 ready 的修改。

如果是本地开发环境, JVM 一般都是 client 模式,可以在你的 IDE 里面设置 JVM 的模式为 server 模式,运行该段代码。

如果想让读线程及时发现 ready 变量的修改,可以使用 volatile关键 字对变量 ready 进行修饰,可以保证所有线程第一时间看到该变量。

对于原子性, Java 提供了 atomic 包,比如对于上篇文章提到的任务计数器示例,我们可以不使用 synchronized ,而使用 AtomicInteger 来达到同样的效果。

AtomicInteger 可以保证自增操作是原子性的。

注意并不是有了原子性及可见性操作,就可以放弃使用锁同步。原子性及可见性并不能保证线程安全,只有在一些特定的场景下才能够达到避免使用锁同步的效果,上面的样例只是为了说明 Java 提供的 Atomvolatile 功能,而特意设计的样例场景。如果真实生产中想使用原子性及可见性替代锁同步时,要认真分析。

结束

这篇文章介绍如何通过不使用锁同步的情况,实现正确的并发访问。至此,并发编程里面两种访问共享可变资源的方式就都介绍完了。下一篇会介绍线程间的通信问题。

推荐阅读:

1. Java并发编程那些事儿(一) ——任务与线程

2. Java8的Stream流真香,没体验过的永远不知道

3. Awk这件上古神兵你会用了吗

4. 手把手教你搭建一套ELK日志搜索运维平台

·END·

花括号MC

Java·大数据·个人成长

Java并发编程那些事儿(三)——ThreadLocal及原子性与可见性

微信号:huakuohao-mc

点一下你会更好看耶

Java并发编程那些事儿(三)——ThreadLocal及原子性与可见性


以上所述就是小编给大家介绍的《Java并发编程那些事儿(三)——ThreadLocal及原子性与可见性》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

iPhone开发实战

iPhone开发实战

2009-10 / 69.00元

《iPhone开发实战》全面探讨了iPhone平台的两种编程方式——Web开发和SDK编程。全书结合示例对这两种编程方式的基本流程、基本原理和基本原则给出了详细而通俗的讲解。在Web开发方面,分别介绍了三个iPhone Web库,即WebKit、iUI和Canvas,并讨论了Web开发环境Dashcode,最后阐述Web应用程序的调试。在SDK开发方面,详细描述其各种组件和功能,包括Xcode、I......一起来看看 《iPhone开发实战》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具