线程 continue -- 4

原创 2004年07月13日 12:01:00

ThreadLocal 的性能
虽然线程局部变量早已赫赫有名并被包括 Posix pthreads 规范在内的很多线程框架支持,但最初的 Java 线程设计中却省略了它,只是在 Java 平台的版本 1.2 中才添加上去。在很多方面,ThreadLocal 仍在发展之中;在版本 1.3 中它被重写,版本 1.4 中又重写了一次,两次都专门是为了性能问题。

在 JDK 1.2 中,ThreadLocal 的实现方式与清单 2 中的方式非常相似,除了用同步 WeakHashMap 代替 HashMap 来存储 values 之外。(以一些额外的性能开销为代价,使用 WeakHashMap 解决了无法对 Thread 对象进行垃圾回收的问题。)不用说,ThreadLocal 的性能是相当差的。

Java 平台版本 1.3 提供的 ThreadLocal 版本已经尽量更好了;它不使用任何同步,从而不存在可伸缩性问题,而且它也不使用弱引用。相反地,人们通过给 Thread 添加一个实例变量(该变量用于保存当前线程的从线程局部变量到它的值的映射的 HashMap)来修改 Thread 类以支持 ThreadLocal。因为检索或设置一个线程局部变量的过程不涉及对可能被另一个线程读写的数据的读写操作,所以您可以不用任何同步就实现 ThreadLocal.get() 和 set()。而且,因为每线程值的引用被存储在自已的 Thread 对象中,所以当对 Thread 进行垃圾回收时,也能对该 Thread 的每线程值进行垃圾回收。

不幸的是,即使有了这些改进,Java 1.3 中的 ThreadLocal 的性能仍然出奇地慢。据我的粗略测量,在双处理器 Linux 系统上的 Sun 1.3 JDK 中进行 ThreadLocal.get() 操作,所耗费的时间大约是无争用同步的两倍。性能这么差的原因是 Thread.currentThread() 方法的花费非常大,占了 ThreadLocal.get() 运行时间的三分之二还多。虽然有这些缺点,JDK 1.3 ThreadLocal.get() 仍然比争用同步快得多,所以如果在任何存在严重争用的地方(可能是有非常多的线程,或者同步块被频繁地执行,或者同步块很大),ThreadLocal 可能仍然要高效得多。

在 Java 平台的最新版本,即版本 1.4b2 中,ThreadLocal 和 Thread.currentThread() 的性能都有了很大提高。有了这些提高,ThreadLocal 应该比其它技术,如用池,更快。由于它比其它技术更简单,也更不易出错,人们最终将发现它是避免线程间出现不希望的交互的有效途径。

ThreadLocal 的好处
ThreadLocal 能带来很多好处。它常常是把有状态类描绘成线程安全的,或者封装非线程安全类以使它们能够在多线程环境中安全地使用的最容易的方式。使用 ThreadLocal 使我们可以绕过为实现线程安全而对何时需要同步进行判断的复杂过程,而且因为它不需要任何同步,所以也改善了可伸缩性。除简单之外,用 ThreadLocal 存储每线程单子或每线程上下文信息在归档方面还有一个颇有价值好处 — 通过使用 ThreadLocal,存储在 ThreadLocal 中的对象都是不被线程共享的是清晰的,从而简化了判断一个类是否线程安全的工作。

我希望您从这个系列中得到了乐趣,也学到了知识,我也鼓励您到我的讨论论坛中来深入研究多线程问题。

 

关于作者
Brian Goetz 是一名软件顾问,过去 15 年来一直是专业软件开发者。他是 Quiotix 的首席顾问,该公司从事软件开发和咨询业务,位于加利福尼亚的 Los Altos。敬请查看 Brian 在流行的业界出版物中已发表和即将发表的论文列表。可通过 brian@quiotix.com 与 Brian 联系。 
 

线程 continue -- 2

清单 2. ThreadLocal 的糟糕实现 public class ThreadLocal {   private Map values = Collections.synchronizedMa...
  • wensilan
  • wensilan
  • 2004年07月13日 11:56
  • 669

java关键字之break与continue的区别(简单明了的小例子)

一.作用与区别 break的作用是跳出当前循环块(for、while、do while)或程序块(switch)。在循环块中的作用是跳出当前正在循环的循环体。在程序块中的作用是中断和下一个case条...
  • tomcat_2014
  • tomcat_2014
  • 2015年10月19日 19:48
  • 1275

双核心四线程变成单核心单线程,肿么办

一、事情起因:        在第二遍看操作系统的过程当中,看到了多处理器系统,当时比较好奇。总觉得这个东东应该指的就是我们平时所说的双核、四核。于是乎,百度一下。百度结果如下图所示。好奇心驱使,打开...
  • qq_26545305
  • qq_26545305
  • 2016年03月02日 19:07
  • 1476

设计四个线程,其中两个线程每次对j+1,两个线程每次 j-1

这是一道典型的java多线程面试题。开路代码之前要明白什么是线程,什么是进程。 通俗来讲,进程就是两个不同的工程,比如说你同时登陆的QQ和YY,他们之间的数据资源和地址空间不是共享的,这两个进程是单...
  • qq_29932025
  • qq_29932025
  • 2017年04月19日 14:18
  • 573

关于“设计4个线程,其中两个线程对j加1,另外两个线程对j减1”的问题

1、代码 public class Test { public static void main(String[] args) { Data data = new Data(); ...
  • vinegar93
  • vinegar93
  • 2016年05月19日 14:32
  • 2260

线程 continue -- 3

清单 4. 用 ThreadLocal 管理每线程调试日志public class DebugLogger {  private static class ThreadLocalList extend...
  • wensilan
  • wensilan
  • 2004年07月13日 11:59
  • 691

cpu的四线程是什么意思?

转:http://zhidao.baidu.com/link?url=0RM55MvghNoFMECeU5z1-zHDNvBuwQDA3QZFgJ1csH_LrfmwBWDqHqdwS5_SVHMB_...
  • pzasdq
  • pzasdq
  • 2016年09月23日 00:26
  • 327

四核8线程与八核的区别

四核八线程是指使用了超线程技术 , 把一个物理核心,模拟成 两个逻辑核心, 理论上要像八颗物理核心一样在同一时间执行八个线程,所以设备管理器和任务管理器中会显示出八个核心,但事实上并不是真正的八个核心...
  • QQQQQQ654
  • QQQQQQ654
  • 2016年11月14日 12:39
  • 6010

lua 中continue的实现

今天写项目的时候要用到c++中的continue,但是lua中并没有continue所以只能自己实现一下 for i=1,10 do while true do ...
  • qq_30392565
  • qq_30392565
  • 2016年11月30日 16:20
  • 7862

oracle存储过程continue

在编写存储过程的过程中需要用到类似于Java循环中continue的功能,但是发现开发环境数据库安装的是oracle 10g并不支持continue语句,现场的测试库和正式库都是使用的11g,11g是...
  • baidu_33412213
  • baidu_33412213
  • 2015年12月17日 16:06
  • 1529
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程 continue -- 4
举报原因:
原因补充:

(最多只允许输入30个字)