论坛首页 Java企业应用论坛

ThreadLocal与synchronized

浏览 107659 次
精华帖 (8) :: 良好帖 (15) :: 新手帖 (9) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-25  
calmness 写道
LZ在ThreadLocal的使用上有误导,ThreadLocal并非是用于解决同步问题的,存在同步问题的问题它也解决不了,比如说一个统计类的系统,你能用ThreadLocal做到吗?难道为每个线程都copy一个计数器吗?那有什么用?ThreadLocal与synchronized 在使用上是没有可比性的,更没有谁替代谁的说法,帖子被评良好会导致不了解的人误解的。


你可能没有看完全文吧!!!
从来没有说过要用ThreadLocal代替synchronized
0 请登录后投票
   发表时间:2007-05-25  
jindw 写道
weiqingfei 写道
jindw 写道

weiqingfei 写道
其实两个本来就没有关系,我想楼主只是想说如何在多线程中活用ThreadLocal。

ThreadLocal的实现本来就比较简单,只是用线程来作为key来寻找本线程中所使用的一个实例,它解决的最主要的问题应该就是减少参数的传递。


说句没有意义的话,事实上。ThreadLocal实现中,作为key的不是线程,而是ThreadLocal本身。


从整体上来看好吧。
不要看到ThreadLocalMap的key是ThreadLocal,就认为寻找线程本地变量实例的key就是ThreadLocal了。

要知道每个线程都会持有一个ThreadLocalMap的实例,我说的key就是这个意思。
key只是找到目标的钥匙,不是只有map才有key。


你的话也有道理,但是,说到这个细节,我还是要说一下,ThreadLocal要比我们简单的想象复杂的多,不单是一个变量存储,它的数据方Thread里面,很明显,在线程销毁时的清理任务。

可以说ThreadLocal是个系统级的API,比我们想象的要复杂一点。


文中那个ThreadLocal的实现代码仅是一些猜想和stub!
为了更好的说明ThreadLocal
0 请登录后投票
   发表时间:2007-05-25  
BirdGu 写道
spiritfrog 写道
XMLDB 写道
LZ把概念搞错了,ThreadLocal就是ThreadLocal,和同步完全没有关系。
ThreadLocal解决的是同一个线程内的资源共享问题,而synchronized 解决的是多个线程间的资源共享问题,两个问题没有可比性。

lz的文章并没有去讨论ThreadLocal就是ThreadLocal有什么关系,只是在说如何保证多线程环境下对共享资源访问的数据安全。文章看完了,简单明了,很到位,是篇好文章。


麻烦你解释一下,ThreadLocal是怎么“保证多线程环境下对共享资源访问的数据安全”的?ThreadLocal使各个线程使用各自不同的数据,这种情况下哪来的“共享资源”?


就是告诉你多线程的时候什么时候用ThreadLocal,什么时候用而synchronized
0 请登录后投票
   发表时间:2007-05-25  
klyuan 写道
BirdGu 写道
spiritfrog 写道
XMLDB 写道
LZ把概念搞错了,ThreadLocal就是ThreadLocal,和同步完全没有关系。
ThreadLocal解决的是同一个线程内的资源共享问题,而synchronized 解决的是多个线程间的资源共享问题,两个问题没有可比性。

lz的文章并没有去讨论ThreadLocal就是ThreadLocal有什么关系,只是在说如何保证多线程环境下对共享资源访问的数据安全。文章看完了,简单明了,很到位,是篇好文章。


麻烦你解释一下,ThreadLocal是怎么“保证多线程环境下对共享资源访问的数据安全”的?ThreadLocal使各个线程使用各自不同的数据,这种情况下哪来的“共享资源”?


就是告诉你多线程的时候什么时候用ThreadLocal,什么时候用而synchronized

事实上,ThreadLocal就是为了不要数据共享,而是每个线程都有自己的数据,ThreadLocal和同步根本是不搭界的,而在楼主的文章里好像更容易把糊涂的人搞糊涂
再举个例子
楼主贴的ThreadLocal的猜想:

public class ThreadLocal   
{   
 private Map values = Collections.synchronizedMap(new HashMap());   
 public Object get()   
 {   
  Thread curThread = Thread.currentThread();    
  Object o = values.get(curThread);    
  if (o == null && !values.containsKey(curThread))   
  {   
   o = initialValue();   
   values.put(curThread, o);    
  }   
  return o;    
 }   
  
 public void set(Object newValue)   
 {   
  values.put(Thread.currentThread(), newValue);   
 }   
  
 public Object initialValue()   
 {   
  return null;    
 }   
}  


但是事实上不是这样的。
ThreadLocal应该是一个工具类,把数据通过ThreadLocal放到线程中去而已,每个线程都有自己的一个ThreadLocalMap(这个Map类是ThreadLocal的一个内部类)来存放这些变量,而楼主的代码是把这个变量存放在ThreadLocal中,在ThreadLocal中又对这个map进行同步。这个明显是不对的
我们看看jdk中的ThreadLocal就知道了:
public Object get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) 
            return map.get(this);

        // Maps are constructed lazily.  if the map for this thread
        // doesn't exist, create it, with this ThreadLocal and its
        // initial value as its only entry.
        Object value = initialValue();
        createMap(t, value);
        return value;
    }

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

    void createMap(Thread t, Object firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }



ps:楼主的文章误导人的字句确实不少(还有代码),如果改过来可投良好
0 请登录后投票
   发表时间:2007-05-25  
ThreadLocal和synchronized除了都和多线程有关外,是没有太多的可比性,不应该放在一起说,这样确实会误导新手。

XMLDB的观点正解:
ThreadLocal解决的是同一个线程内的资源共享问题,而synchronized 解决的是多个线程间的资源共享问题,两个问题没有可比性。
0 请登录后投票
   发表时间:2007-05-25  
ahuaxuan 写道

但是事实上不是这样的。
ThreadLocal应该是一个工具类,把数据通过ThreadLocal放到线程中去而已,每个线程都有自己的一个ThreadLocalMap(这个Map类是ThreadLocal的一个内部类)来存放这些变量,而楼主的代码是把这个变量存放在ThreadLocal中,在ThreadLocal中又对这个map进行同步。这个明显是不对的
ps:楼主的文章误导人的字句确实不少(还有代码),如果改过来可投良好

应该是每个变量有一个ThreadLocalMap,然后每个ThreadLocalMap被所有线程共享吧?

我觉得楼主把这两个东西拿到一起来讨论是合理地,因为现实情况是:开发人员在很多没有必要用实例变量的场合却使用了一个实例变量,由此导致为了线程安全而使用synchronize,增加了复杂度,还有性能\死锁问题
而这种情况是可以用ThreadLocal来解决的
当然,需要在线程之间共享数据的时候,还是要用实例变量
0 请登录后投票
   发表时间:2007-05-25  
引用

Synchronized还是ThreadLocal?
ThreadLocal以空间换取时间,提供了一种非常简便的多线程实现方式。因为多个线程并发访问无需进行等待,所以使用ThreadLocal会获得更大的性能。虽然使用ThreadLocal会带来更多的内存开销,但这点开销是微不足道的。因为保存在ThreadLocal中的对象,通常都是比较小的对象。另外使用ThreadLocal不能使用原子类型,只能使用Object类型。ThreadLocal的使用比synchronized要简单得多。



其他先不说,我想通过这段话就可以看出你把Synchronized和ThreadLocal放在可比可替换的情况下了吧,至少这里就已经做出了误导。
0 请登录后投票
   发表时间:2007-05-25  
to daquan: ahuaxuan说的没错。
0 请登录后投票
   发表时间:2007-05-25  
ahuaxuan 写道

我们看看jdk中的ThreadLocal就知道了:
public Object get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) 
            return map.get(this);

        // Maps are constructed lazily.  if the map for this thread
        // doesn't exist, create it, with this ThreadLocal and its
        // initial value as its only entry.
        Object value = initialValue();
        createMap(t, value);
        return value;
    }

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

    void createMap(Thread t, Object firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }



哦,是我搞错了.又仔细看了一下这段代码
0 请登录后投票
   发表时间:2007-05-25  
是啊,楼主和好多人一样对ThreadLocal的理解有较大的偏差,可以看看这一篇文章:http://www.iteye.com/topic/71554,里面介绍的很清楚,相信对大家有帮助。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics