论坛首页 Java企业应用论坛

ThreadLocal与synchronized

浏览 107788 次
精华帖 (8) :: 良好帖 (15) :: 新手帖 (9) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-30  
lujh99 写道
这种情况确实没有必要存在,但是如果非要制造出这种情况也是可能的。

比如Spring应用中的service类是单例的,action类是多例的,service被注入到action中。如果service类中有一个成员对象A(纯粹举例子,实际不会这么用),action类中有个static的ThreadLocal。
那么有多个request的话就有多个线程在运行,在线程中可以将对象A通过ThreadLocal的set方法放到线程中,通过ThreadLocal的get方法取出来,难道你说放到多个线程中的对象A不是同一个对象吗?取出来的不是同一个对象吗?实际放进去的就是一个引用而已。怎么能说“保证了任何一个线程都拥有属于自己的实例”呢?

以上例子仅仅为了说法这个说法是不对的,实际不会这样使用。跟action类是不是多例也没有太大关系。

另:小伙怎么跑到上海去了

在你说的这种情形下确实是这样的
但是也确实不会这样用的,呵呵

ps:来上海已经快两个月了:)
0 请登录后投票
   发表时间:2007-05-30  
lujh99 写道
eway 写道
ThreadLocal本身的作用是保证任何一个线程都拥有属于自己的实例,...

这个正是楼主错误的观点,
如果一个类中定义了一个static的ThreadLocal,一个共享对象可以通过该ThreadLocal的set设置到多个线程的ThreadLocalMap中,但是这多个线程的ThreadLocalMap中存着的仅仅是该对象的引用,指向那个共享对象,而不是什么副本,通过ThreadLocal的get方法取到的是就是那个共享对象本身,共享访问安全问题还是要靠其他方法来解决。



用过HibernateUtil吧?看看怎么写的。。。你明白不为什么要用这个类?不是为了保证每个线程都有一个属于自己的独立的session,同时这个session又是一个线程内部所共享的么?

  public static final ThreadLocal sessionLocal = new ThreadLocal();

  public static Session currentSession() throws HibernateException {
    Session session = (Session) sessionLocal.get();
    if (session == null) {
      session = sessionFactory.openSession();
      sessionLocal.set(session);
    }
    return session;
  }


再看看ThreadLocal的set方法干啥! map.put(Thread.currentThread,object);

如果你读懂了,应该可以明白每个不同的线程都会在ThreadLocal中put进去不同的新session对象,而不是你理解的不同引用。

你不觉得自己太牵强了么?拿一个不自己都说在实际中不会用的例子过来证明什么,能证明什么呢?

你不会不知道ThreadLocal在Hibernate中的上述实际应用吧?这样的用法才是ThreadLocal的真正应用的场景,也就是我之前说过的,这个类来保证每个线程一个实例,并且每个线程都只有一个该线程内部共享的实例。

想告诉你lujh99,你对ThreadLocal的理解才是彻头彻尾的错误,比楼主理解的偏差相差的更远!
0 请登录后投票
   发表时间:2007-05-30  
eway 写道

再看看ThreadLocal的set方法干啥! map.put(Thread.currentThread,object);



拜托,那是楼主自己瞎写的,你还真信了,即使真是这样,放进去的也是一个引用啊。

不跟你争了,你还是去看看java的源码吧。
0 请登录后投票
   发表时间:2007-05-30  
lujh99 写道
eway 写道

再看看ThreadLocal的set方法干啥! map.put(Thread.currentThread,object);



拜托,那是楼主自己瞎写的,你还真信了,即使真是这样,放进去的也是一个引用啊。

不跟你争了,你还是去看看java的源码吧。


你可真逗,拿java源码给你看。。。 这就是ThreadLocal的源码了,你觉得和上面的不是一个意思?

    public void set(Object value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) 
            map.set(this, value);
        else
            createMap(t, value);
    }
0 请登录后投票
   发表时间:2007-05-30  
lujh99 写道
真是无语了...


应该说语塞,和无语有区别滴。。。倒想听听你还有什么"高论"?
0 请登录后投票
   发表时间:2007-05-30  
我也不想说你什么了,只能说你太粗心了,再仔细看看吧
0 请登录后投票
   发表时间:2007-05-30  
那年夏天 写道
终于找到详细的ThreadLocal介绍了

阳光晒晒 写道
汗。。。如果有其它的建议先看看别的。。
这翩文章很有争议性。

仔细看过Hibernate中对Session 在不同的线程里保存的例子之后,还是感觉楼主的解释是很清晰的
0 请登录后投票
   发表时间:2007-05-30  
ThreadLocal确实没办法保证一线程一个实例。很可能这个实例本来就是多线程共享的。
假如本来就被多个线程共享了,那就没办法保证安全了!
就像struts action的一个属性。放进去还是非线程安全。
这样使用类似set(new Object());不让别的线程拿到这个对象的引用,这样才能线程安全。
不过和synchronized这种虚拟机直接强制同步是本质上的不同。
0 请登录后投票
   发表时间:2007-05-30  
eway 写道
lujh99 写道
真是无语了...


应该说语塞,和无语有区别滴。。。倒想听听你还有什么"高论"?


想听听你现在的看法是怎样的?
0 请登录后投票
   发表时间:2007-05-30  
例子不好,说明不了什么问题,
第一个例子和第二个例子边都挨不上;
第一个例子,两个Thread,分享一个Student实例
第二个呢?ThreadLocal类不是 new ThreadLocal(),然后set一下,就多线程共享的。
0 请登录后投票
论坛首页 Java企业应用版

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