- 浏览: 39783 次
- 性别:
- 来自: 深圳
最新评论
-
shuaiji:
有点看不懂呢
JAVA序列化基础知识Serializable与Externalizable的区别 -
nepalon:
LZ写的在getCount和setCount中用synchro ...
ThreadLocal and synchronized 补充 -
ecoll:
两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的 ...
ThreadLocal and synchronized 补充 -
max.h.chen:
<div class="quote_title ...
ThreadLocal and synchronized 补充 -
shaucle:
你可以看下源码,并不是你们说的那么复杂
都是人想出来的解决方 ...
ThreadLocal and synchronized 补充
http://www.iteye.com/topic/81936?page=1
以上是原贴.
本文只是针对原贴的补充.
对于ThreadLocal和synchronized的区别,请看下面的例子估计大家更能清楚认识.希望我能在kyluan原贴的基础上把这个区别说清楚.
btw:这个例子是一个使用ThreadLocal不当的例子,请不要在项目中如此使用.
首先产生一个引用对象staff1 .
然后产生10个MyThread 类型的线程对象.
这10个线程中每一个都持有私有的ThreadLocal对象.
在这10个线程开始start的时候,在run方法中将staff1对象设置到各自私有的ThreadLocal对象中.
当我们注释掉staff1中的synchronized时候,我们马上就看到出现了count数据的不一致.
只有当我们使用synchronized,不一致的情况解决了.
当StaffInfoVO的count的set/get方法不是synchronized的时候,虽然每个Thread维护了一个对应的ThreadLocal,而ThreadLocal只是对于Thread对象中的ThreadLocalMap的接口暴露(get/set添加和取得保存的对象)对于被保存的对象,只是保存了引用的情况下,并且被保存对象的状态改变的方法不是synchronized的时候,并不能保证同步. 这个是ThreadLocal的局限性.并没有synchronized关键字那么安全.在我看来ThreadLocal MS不是用来处理同步,而只是为了保存当前线程自有的某个状态.当ThreadLocal.set(Object obj)方法时,取得Thread.currentThread.ThreadLocalMap对象,然后将自己作为KEY保存到ThreadLocalMap中.ThreadLocal.get处理方法类似.
所以最后我得出的结论就是:synchronized是用来处理多线程环境下的数据同步,而ThreadLocal只是为了保存当前线程私有的某种状态.
以上内容,如有不当,请指出.
谢谢.
开什么玩笑呢,消息传递和共享内存是两种线/进程间数据共享的方式,这前面已经有人说过了。怎么就得出‘消息传递,也就是我说的“线程间共享数据”synchronized’这样的结论呢?消息传递是将大家需要共享的数据以消息的方式,通过定义和实现消息栈,来达到数据的共享的目的。而共享内存则是将数据写到一个大家都能互访问的同一块内存区域(映射为各自的虚拟内存地址),为了防止race condition所以才有synchronized机制。synchronized是共享内存搞出来的玩意,跟数据共享没什么关系,这是个白马非马的问题。概念就没搞清楚。
这样更加是误导,ThreadLocal是与Thread紧密耦合的,没有上面这么简单。
但这的确是我以前一个项目的实现
没有ThreadLocal之前Thread和ThreadLocal无法紧密耦合(你不能改Thead)
紧密耦合主要是实现线程之间传递inheritableThreadLocals的问题
ThreadLocalMap是ThreadLocal内部的一个WeakReference的Hashmap实现
而Thread.currentThread();已经处理了线程问题,所以synchronized也可以不用
至于是否误导,我看不同的人应该有不同的看法。
ps:本来我不想很detail的。
这样更加是误导,ThreadLocal是与Thread紧密耦合的,没有上面这么简单。
非常言简意赅.也许叫ThreadLocalDataHolder更好.^_^
我觉得应该叫ThreadLocalDataRef
因为,ThreadLocal本身是不持有对象的。就算ThreadLocal没被销毁,与他相关的对象也可能被回收
ThreadLocal都没有共享数据了,还有什么一致性问题?原来你解决问题的方法就是取消这个问题?
3.原文已经总结了"但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂"
很多的朋友都没有看完全文说胡乱评论!!!
synchronized关键字的目的并不是提供线程间的数据共享,而是为多线程共享的数据结构提供一个互斥机制,保护共享数据处在一个一致的状态,避免在多线程访问时出现race condition破坏共享数据的一致性。
我所知道的并发编程模型有两种:基于共享内存和基于消息传递。Java属于共享内存的并发模型,而erlang这样的属于消息传递模型。换句话来说,在线程间共享数据,如果不在意数据一致性的话,直接共享就可以了。所以synchronized用于在线程间共享数据的这个说法其实是不对的。
ThreadLocal前面有人说的很清楚了,其实就是thread private data, 前面几位有自己实现thread local的,其实都不能算错。effective java里的Item 32有一节就在讨论ThreadLocal for capabilities. 算是标准答案吧。当然了,往ThreadLocal里面塞一个要给多个线程共享的数据也没什么不妥的,但是这个用法是如此诡异,几乎要划到反模式里面去了吧?
保护数据的一致性ThreadLocal会更好用一点!
消息传递,也就是我说的“线程间共享数据”synchronized
即使要这么做(想不出来这样做的理由),为了保证这个数据的一致性,synchronized仍然是需要的。
3.原文已经总结了"但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂"
很多的朋友都没有看完全文说胡乱评论!!!
synchronized关键字的目的并不是提供线程间的数据共享,而是为多线程共享的数据结构提供一个互斥机制,保护共享数据处在一个一致的状态,避免在多线程访问时出现race condition破坏共享数据的一致性。
我所知道的并发编程模型有两种:基于共享内存和基于消息传递。Java属于共享内存的并发模型,而erlang这样的属于消息传递模型。换句话来说,在线程间共享数据,如果不在意数据一致性的话,直接共享就可以了。所以synchronized用于在线程间共享数据的这个说法其实是不对的。
ThreadLocal前面有人说的很清楚了,其实就是thread private data, 前面几位有自己实现thread local的,其实都不能算错。effective java里的Item 32有一节就在讨论ThreadLocal for capabilities. 算是标准答案吧。当然了,往ThreadLocal里面塞一个要给多个线程共享的数据也没什么不妥的,但是这个用法是如此诡异,几乎要划到反模式里面去了吧?
有点差别。
java的ThreadLocal里面没有自己的map成员,而是把map放到在使用Thread类中。
而shaucle给出的自己threadLocal实现的例子里面拥有一个map,这个map会越来越大,所以还需要有另外的thread来定期清理map中thread已死的那些key\
俺只是随意写一下,说明一下一些context的一般实现原理
不过程序员一般都喜欢detail 进去...
首先我声明:你没有看完原贴的全文就妄加评论!!!
1。例子只是为了说明ThreadLocal,并不是叫你那样去写代码!
2.原文的目的是说明在多线程程序中什么时候用synchronized ,什么时候用ThreadLocal.
并不打算去深入的说明ThreadLocal.
3.原文已经总结了"但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂"
很多的朋友都没有看完全文说胡乱评论!!!
我并不是评论你的贴子好不好什么的.
只是深入一下,将一些感觉上模拟两可的东西用一个例子表述清楚下.
在这个例子中不是一眼就看出什么时候该用ThreadLocal什么时候用synchronized了吗?
最后研究一下ThreadLocal的代码吧:
ThreadLocal代码片段:
以上代码就看出,取的是当前线程持有的ThreadLocalMap,然后从这个Map中取对象.
ThreadLocalMap的代码片段:
Thread代码片段:
有兴趣的可以自己去研究下.
首先我声明:你没有看完原贴的全文就妄加评论!!!
1。例子只是为了说明ThreadLocal,并不是叫你那样去写代码!
2.原文的目的是说明在多线程程序中什么时候用synchronized ,什么时候用ThreadLocal.
并不打算去深入的说明ThreadLocal.
3.原文已经总结了"但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂"
很多的朋友都没有看完全文说胡乱评论!!!
有点差别。
java的ThreadLocal里面没有自己的map成员,而是把map放到在使用Thread类中。
而shaucle给出的自己threadLocal实现的例子里面拥有一个map,这个map会越来越大,所以还需要有另外的thread来定期清理map中thread已死的那些key
以上是原贴.
本文只是针对原贴的补充.
对于ThreadLocal和synchronized的区别,请看下面的例子估计大家更能清楚认识.希望我能在kyluan原贴的基础上把这个区别说清楚.
btw:这个例子是一个使用ThreadLocal不当的例子,请不要在项目中如此使用.
public class TestThreadLocal { public static void main(String[] args) throws Exception { ThreadLocal myThreadLocal = new ThreadLocal(); StaffInfoVO staff1 = new StaffInfoVO(); staff1.setName("default"); staff1.setCount(new Integer(1)); for (int i = 0; i < 10; i++) { MyThread myt = new MyThread(staff1, myThreadLocal); Thread t1 = new Thread(myt); t1.setName("myThread" + i); t1.start(); } } public static class MyThread implements Runnable { private StaffInfoVO staff1; private ThreadLocal myThreadLocal; public MyThread(StaffInfoVO staff, ThreadLocal myThreadLocal) { staff1 = staff; this.myThreadLocal = myThreadLocal; System.out.println("con staff" + staff); } public void run() { myThreadLocal.set(staff1); while (true) { StaffInfoVO staff = (StaffInfoVO) myThreadLocal.get(); // System.out.println("staff:" + staff); int i = staff.getCount().intValue(); System.out.println("Thread name:" + Thread.currentThread().getName() + " staff count:" + i); staff.setCount(new Integer(i + 1)); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } public class StaffInfoVO implements Serializable { /** * */ private static final long serialVersionUID = -57676961756664705L; private String name; private String staffNo; private List roles; private Integer count; // 如果不使用synchronized,大家一眼就看到区别了. public synchronized Integer getCount() { return count; } // 如果不使用synchronized,大家一眼就看到区别了. public synchronized void setCount(Integer count) { this.count = count; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } public String getStaffNo() { return staffNo; } public void setStaffNo(String staffNo) { this.staffNo = staffNo; } }
首先产生一个引用对象staff1 .
然后产生10个MyThread 类型的线程对象.
这10个线程中每一个都持有私有的ThreadLocal对象.
在这10个线程开始start的时候,在run方法中将staff1对象设置到各自私有的ThreadLocal对象中.
当我们注释掉staff1中的synchronized时候,我们马上就看到出现了count数据的不一致.
只有当我们使用synchronized,不一致的情况解决了.
当StaffInfoVO的count的set/get方法不是synchronized的时候,虽然每个Thread维护了一个对应的ThreadLocal,而ThreadLocal只是对于Thread对象中的ThreadLocalMap的接口暴露(get/set添加和取得保存的对象)对于被保存的对象,只是保存了引用的情况下,并且被保存对象的状态改变的方法不是synchronized的时候,并不能保证同步. 这个是ThreadLocal的局限性.并没有synchronized关键字那么安全.在我看来ThreadLocal MS不是用来处理同步,而只是为了保存当前线程自有的某个状态.当ThreadLocal.set(Object obj)方法时,取得Thread.currentThread.ThreadLocalMap对象,然后将自己作为KEY保存到ThreadLocalMap中.ThreadLocal.get处理方法类似.
所以最后我得出的结论就是:synchronized是用来处理多线程环境下的数据同步,而ThreadLocal只是为了保存当前线程私有的某种状态.
以上内容,如有不当,请指出.
谢谢.
评论
31 楼
nepalon
2008-04-14
LZ写的在getCount和setCount中用synchronized也不能达到同步效果的,要改为
synchronized (staff) {
int i = staff.getCount().intValue();
System.out.println("Thread name:" + Thread.currentThread().getName() + " staff count:" + i);
staff.setCount(new Integer(i + 1));
}
synchronized (staff) {
int i = staff.getCount().intValue();
System.out.println("Thread name:" + Thread.currentThread().getName() + " staff count:" + i);
staff.setCount(new Integer(i + 1));
}
30 楼
ecoll
2007-06-16
两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行通信的有效方式;而ThreadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样当然不需要对多个线程进行同步了。所以,如果你需要进行多个线程之间进行通信,则使用同步机制;如果需要隔离多个线程之间的共享冲突,可以使用ThreadLocal
29 楼
max.h.chen
2007-05-27
klyuan 写道
保护数据的一致性ThreadLocal会更好用一点!
消息传递,也就是我说的“线程间共享数据”synchronized
消息传递,也就是我说的“线程间共享数据”synchronized
开什么玩笑呢,消息传递和共享内存是两种线/进程间数据共享的方式,这前面已经有人说过了。怎么就得出‘消息传递,也就是我说的“线程间共享数据”synchronized’这样的结论呢?消息传递是将大家需要共享的数据以消息的方式,通过定义和实现消息栈,来达到数据的共享的目的。而共享内存则是将数据写到一个大家都能互访问的同一块内存区域(映射为各自的虚拟内存地址),为了防止race condition所以才有synchronized机制。synchronized是共享内存搞出来的玩意,跟数据共享没什么关系,这是个白马非马的问题。概念就没搞清楚。
28 楼
shaucle
2007-05-25
你可以看下源码,并不是你们说的那么复杂
都是人想出来的解决方案嘛.
都是人想出来的解决方案嘛.
27 楼
shaucle
2007-05-25
jindw 写道
shaucle 写道
MyThreadLocal{
Map map = new HashMap();
get(){
return map.get(Thread.currentThread());
}
set(Object o){
map.put(Thread.currentThread(), o);
}
}
Map map = new HashMap();
get(){
return map.get(Thread.currentThread());
}
set(Object o){
map.put(Thread.currentThread(), o);
}
}
这样更加是误导,ThreadLocal是与Thread紧密耦合的,没有上面这么简单。
但这的确是我以前一个项目的实现
没有ThreadLocal之前Thread和ThreadLocal无法紧密耦合(你不能改Thead)
紧密耦合主要是实现线程之间传递inheritableThreadLocals的问题
ThreadLocalMap是ThreadLocal内部的一个WeakReference的Hashmap实现
而Thread.currentThread();已经处理了线程问题,所以synchronized也可以不用
至于是否误导,我看不同的人应该有不同的看法。
ps:本来我不想很detail的。
26 楼
jindw
2007-05-25
shaucle 写道
MyThreadLocal{
Map map = new HashMap();
get(){
return map.get(Thread.currentThread());
}
set(Object o){
map.put(Thread.currentThread(), o);
}
}
Map map = new HashMap();
get(){
return map.get(Thread.currentThread());
}
set(Object o){
map.put(Thread.currentThread(), o);
}
}
这样更加是误导,ThreadLocal是与Thread紧密耦合的,没有上面这么简单。
25 楼
jindw
2007-05-25
dovecat 写道
shaucle 写道
ThreadLocal理解成CurrentThreadContext就行了.
也对!其实我们光看这个类的名字就知道了.ThreadLocal!
非常言简意赅.也许叫ThreadLocalDataHolder更好.^_^
我觉得应该叫ThreadLocalDataRef
因为,ThreadLocal本身是不持有对象的。就算ThreadLocal没被销毁,与他相关的对象也可能被回收
24 楼
shaucle
2007-05-25
越来越偏...
23 楼
Qieqie
2007-05-25
“数据一致性”和ThreadLocal无关,这是两个概念
klyuan似乎混淆了概念。
所谓的数据一致性,是指数据从一个状态到另外一个状态要保持一致性,不能被破坏。
一般在并发对共享数据的访问不加有效控制就可能导致不一致性。
你说的通过java程序加同步锁来保证按顺序访问共享数据保持一致性当然没有问题。
但是ThreadLocal与此没有关系,很多人已经指出这一点了:
ThreadLocal里面保存的是每个线程独有的数据,这些数据不是并发“共享数据”,对这些数据没有“一致性”的说法
klyuan似乎混淆了概念。
所谓的数据一致性,是指数据从一个状态到另外一个状态要保持一致性,不能被破坏。
一般在并发对共享数据的访问不加有效控制就可能导致不一致性。
你说的通过java程序加同步锁来保证按顺序访问共享数据保持一致性当然没有问题。
但是ThreadLocal与此没有关系,很多人已经指出这一点了:
ThreadLocal里面保存的是每个线程独有的数据,这些数据不是并发“共享数据”,对这些数据没有“一致性”的说法
22 楼
BirdGu
2007-05-25
引用
保护数据的一致性ThreadLocal会更好用一点!
消息传递,也就是我说的“线程间共享数据”synchronized
消息传递,也就是我说的“线程间共享数据”synchronized
ThreadLocal都没有共享数据了,还有什么一致性问题?原来你解决问题的方法就是取消这个问题?
21 楼
klyuan
2007-05-25
xin_wang 写道
klyuan 写道
3.原文已经总结了"但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂"
很多的朋友都没有看完全文说胡乱评论!!!
synchronized关键字的目的并不是提供线程间的数据共享,而是为多线程共享的数据结构提供一个互斥机制,保护共享数据处在一个一致的状态,避免在多线程访问时出现race condition破坏共享数据的一致性。
我所知道的并发编程模型有两种:基于共享内存和基于消息传递。Java属于共享内存的并发模型,而erlang这样的属于消息传递模型。换句话来说,在线程间共享数据,如果不在意数据一致性的话,直接共享就可以了。所以synchronized用于在线程间共享数据的这个说法其实是不对的。
ThreadLocal前面有人说的很清楚了,其实就是thread private data, 前面几位有自己实现thread local的,其实都不能算错。effective java里的Item 32有一节就在讨论ThreadLocal for capabilities. 算是标准答案吧。当然了,往ThreadLocal里面塞一个要给多个线程共享的数据也没什么不妥的,但是这个用法是如此诡异,几乎要划到反模式里面去了吧?
保护数据的一致性ThreadLocal会更好用一点!
消息传递,也就是我说的“线程间共享数据”synchronized
20 楼
BirdGu
2007-05-25
引用
当然了,往ThreadLocal里面塞一个要给多个线程共享的数据也没什么不妥的,但是这个用法是如此诡异,几乎要划到反模式里面去了吧?
即使要这么做(想不出来这样做的理由),为了保证这个数据的一致性,synchronized仍然是需要的。
19 楼
xin_wang
2007-05-25
klyuan 写道
3.原文已经总结了"但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂"
很多的朋友都没有看完全文说胡乱评论!!!
synchronized关键字的目的并不是提供线程间的数据共享,而是为多线程共享的数据结构提供一个互斥机制,保护共享数据处在一个一致的状态,避免在多线程访问时出现race condition破坏共享数据的一致性。
我所知道的并发编程模型有两种:基于共享内存和基于消息传递。Java属于共享内存的并发模型,而erlang这样的属于消息传递模型。换句话来说,在线程间共享数据,如果不在意数据一致性的话,直接共享就可以了。所以synchronized用于在线程间共享数据的这个说法其实是不对的。
ThreadLocal前面有人说的很清楚了,其实就是thread private data, 前面几位有自己实现thread local的,其实都不能算错。effective java里的Item 32有一节就在讨论ThreadLocal for capabilities. 算是标准答案吧。当然了,往ThreadLocal里面塞一个要给多个线程共享的数据也没什么不妥的,但是这个用法是如此诡异,几乎要划到反模式里面去了吧?
18 楼
shaucle
2007-05-25
Qieqie 写道
shaucle 写道
MyThreadLocal{
Map map = new HashMap();
get(){
return map.get(Thread.currentThread());
}
set(Object o){
map.put(Thread.currentThread(), o);
}
}
Map map = new HashMap();
get(){
return map.get(Thread.currentThread());
}
set(Object o){
map.put(Thread.currentThread(), o);
}
}
dovecat 写道
shaucle 写道
俺以前一个项目在没有ThreadLocal时的实现...
原理上是差不多的.有点差别。
java的ThreadLocal里面没有自己的map成员,而是把map放到在使用Thread类中。
而shaucle给出的自己threadLocal实现的例子里面拥有一个map,这个map会越来越大,所以还需要有另外的thread来定期清理map中thread已死的那些key
俺只是随意写一下,说明一下一些context的一般实现原理
不过程序员一般都喜欢detail 进去...
17 楼
moshalanye
2007-05-25
作为新手我赞同lz的做法,并不是每个人都对每个lz的看法和见解都能很好或是100%的理解,我没有看过原贴,但是我从这张贴上学到了不少,当然包括原贴作者的宝贵见解,每个人在理解别人的东西时候加上自己的见解和猜测时本来就是一种学习的过程,难道在别人思考你的见解时你不该高兴点吗?作为比别人强的人,让别人的思维转向一个更正确的方向不是更让人尊敬些麻!也许是我水平问题,比较喜欢这种jdk的基础讨论,感觉通过这些成长不少,所以不管是好的还是坏的,我都希望从这些中得到更多的启发。作为一个成长的新手我也会更尊敬各位走在我老前面的老大! :)
16 楼
dovecat
2007-05-25
klyuan 写道
首先我声明:你没有看完原贴的全文就妄加评论!!!
1。例子只是为了说明ThreadLocal,并不是叫你那样去写代码!
2.原文的目的是说明在多线程程序中什么时候用synchronized ,什么时候用ThreadLocal.
并不打算去深入的说明ThreadLocal.
3.原文已经总结了"但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂"
很多的朋友都没有看完全文说胡乱评论!!!
我并不是评论你的贴子好不好什么的.
只是深入一下,将一些感觉上模拟两可的东西用一个例子表述清楚下.
在这个例子中不是一眼就看出什么时候该用ThreadLocal什么时候用synchronized了吗?
最后研究一下ThreadLocal的代码吧:
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; } public void set(Object value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; } void createMap(Thread t, Object firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
以上代码就看出,取的是当前线程持有的ThreadLocalMap,然后从这个Map中取对象.
ThreadLocalMap的代码片段:
static class ThreadLocalMap { /** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */ private static class Entry extends WeakReference { /** The value associated with this ThreadLocal. */ private Object value; private Entry(ThreadLocal k, Object v) { super(k); value = v; } } ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); } // 被ThreadLocal的get/set方法暴露给外部调用 private Object get(ThreadLocal key) { // 通过ThreadLocal的hashcode和entry[] table 的大小获得index int i = key.threadLocalHashCode & (table.length - 1); Entry e = table[i]; if (e != null && e.get() == key) return e.value; // 注意在此方法中将调用ThreadLocal.initialValue方法. return getAfterMiss(key, i, e); } private void set(ThreadLocal key, Object value) { // We don't use a fast path as with get() because it is at // least as common to use set() to create new entries as // it is to replace existing ones, in which case, a fast // path would fail more often than not. Entry[] tab = table; int len = tab.length; int i = key.threadLocalHashCode & (len-1); for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { Object k = e.get(); if (k == key) { e.value = value; return; } if (k == null) { replaceStaleEntry(key, value, i, false); return; } } // 重新将ThreadLocal的size table 和threshold调整大小,便于重新计算hashcode tab[i] = new Entry(key, value); if (++size >= threshold) rehash(); }
Thread代码片段:
ThreadLocal.ThreadLocalMap threadLocals = null;
有兴趣的可以自己去研究下.
15 楼
klyuan
2007-05-25
dovecat 写道
http://www.iteye.com/topic/81936?page=1
以上是原贴.
本文只是针对原贴的补充.
对于ThreadLocal和synchronized的区别,请看下面的例子估计大家更能清楚认识.希望我能在kyluan原贴的基础上把这个区别说清楚.
btw:这个例子是一个使用ThreadLocal不当的例子,请不要在项目中如此使用.
首先产生一个引用对象staff1 .
然后产生10个MyThread 类型的线程对象.
这10个线程中每一个都持有私有的ThreadLocal对象.
在这10个线程开始start的时候,在run方法中将staff1对象设置到各自私有的ThreadLocal对象中.
当我们注释掉staff1中的synchronized时候,我们马上就看到出现了count数据的不一致.
只有当我们使用synchronized,不一致的情况解决了.
当StaffInfoVO的count的set/get方法不是synchronized的时候,虽然每个Thread维护了一个对应的ThreadLocal,而ThreadLocal只是对于Thread对象中的ThreadLocalMap的接口暴露(get/set添加和取得保存的对象)对于被保存的对象,只是保存了引用的情况下,并且被保存对象的状态改变的方法不是synchronized的时候,并不能保证同步. 这个是ThreadLocal的局限性.并没有synchronized关键字那么安全.在我看来ThreadLocal MS不是用来处理同步,而只是为了保存当前线程自有的某个状态.当ThreadLocal.set(Object obj)方法时,取得Thread.currentThread.ThreadLocalMap对象,然后将自己作为KEY保存到ThreadLocalMap中.ThreadLocal.get处理方法类似.
所以最后我得出的结论就是:synchronized是用来处理多线程环境下的数据同步,而ThreadLocal只是为了保存当前线程私有的某种状态.
以上内容,如有不当,请指出.
谢谢.
以上是原贴.
本文只是针对原贴的补充.
对于ThreadLocal和synchronized的区别,请看下面的例子估计大家更能清楚认识.希望我能在kyluan原贴的基础上把这个区别说清楚.
btw:这个例子是一个使用ThreadLocal不当的例子,请不要在项目中如此使用.
public class TestThreadLocal { public static void main(String[] args) throws Exception { ThreadLocal myThreadLocal = new ThreadLocal(); StaffInfoVO staff1 = new StaffInfoVO(); staff1.setName("default"); staff1.setCount(new Integer(1)); for (int i = 0; i < 10; i++) { MyThread myt = new MyThread(staff1, myThreadLocal); Thread t1 = new Thread(myt); t1.setName("myThread" + i); t1.start(); } } public static class MyThread implements Runnable { private StaffInfoVO staff1; private ThreadLocal myThreadLocal; public MyThread(StaffInfoVO staff, ThreadLocal myThreadLocal) { staff1 = staff; this.myThreadLocal = myThreadLocal; System.out.println("con staff" + staff); } public void run() { myThreadLocal.set(staff1); while (true) { StaffInfoVO staff = (StaffInfoVO) myThreadLocal.get(); // System.out.println("staff:" + staff); int i = staff.getCount().intValue(); System.out.println("Thread name:" + Thread.currentThread().getName() + " staff count:" + i); staff.setCount(new Integer(i + 1)); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } public class StaffInfoVO implements Serializable { /** * */ private static final long serialVersionUID = -57676961756664705L; private String name; private String staffNo; private List roles; private Integer count; // 如果不使用synchronized,大家一眼就看到区别了. public synchronized Integer getCount() { return count; } // 如果不使用synchronized,大家一眼就看到区别了. public synchronized void setCount(Integer count) { this.count = count; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } public String getStaffNo() { return staffNo; } public void setStaffNo(String staffNo) { this.staffNo = staffNo; } }
首先产生一个引用对象staff1 .
然后产生10个MyThread 类型的线程对象.
这10个线程中每一个都持有私有的ThreadLocal对象.
在这10个线程开始start的时候,在run方法中将staff1对象设置到各自私有的ThreadLocal对象中.
当我们注释掉staff1中的synchronized时候,我们马上就看到出现了count数据的不一致.
只有当我们使用synchronized,不一致的情况解决了.
当StaffInfoVO的count的set/get方法不是synchronized的时候,虽然每个Thread维护了一个对应的ThreadLocal,而ThreadLocal只是对于Thread对象中的ThreadLocalMap的接口暴露(get/set添加和取得保存的对象)对于被保存的对象,只是保存了引用的情况下,并且被保存对象的状态改变的方法不是synchronized的时候,并不能保证同步. 这个是ThreadLocal的局限性.并没有synchronized关键字那么安全.在我看来ThreadLocal MS不是用来处理同步,而只是为了保存当前线程自有的某个状态.当ThreadLocal.set(Object obj)方法时,取得Thread.currentThread.ThreadLocalMap对象,然后将自己作为KEY保存到ThreadLocalMap中.ThreadLocal.get处理方法类似.
所以最后我得出的结论就是:synchronized是用来处理多线程环境下的数据同步,而ThreadLocal只是为了保存当前线程私有的某种状态.
以上内容,如有不当,请指出.
谢谢.
首先我声明:你没有看完原贴的全文就妄加评论!!!
1。例子只是为了说明ThreadLocal,并不是叫你那样去写代码!
2.原文的目的是说明在多线程程序中什么时候用synchronized ,什么时候用ThreadLocal.
并不打算去深入的说明ThreadLocal.
3.原文已经总结了"但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂"
很多的朋友都没有看完全文说胡乱评论!!!
14 楼
Godlikeme
2007-05-25
HashMap的put方法不是同步的,有并发冲突。
threadLocal的map是保存在thread中的,不需要同步。
threadLocal的map是保存在thread中的,不需要同步。
13 楼
dovecat
2007-05-25
恩,我是说原理上,除开后来针对设计上的处理,将ThreadLocal.ThreadLocalMap赋给Thread.threadLocals变量,而ThreadLocal就变成了包装和操作ThreadLocalMap的接口.
12 楼
Qieqie
2007-05-25
shaucle 写道
MyThreadLocal{
Map map = new HashMap();
get(){
return map.get(Thread.currentThread());
}
set(Object o){
map.put(Thread.currentThread(), o);
}
}
Map map = new HashMap();
get(){
return map.get(Thread.currentThread());
}
set(Object o){
map.put(Thread.currentThread(), o);
}
}
dovecat 写道
shaucle 写道
俺以前一个项目在没有ThreadLocal时的实现...
原理上是差不多的.有点差别。
java的ThreadLocal里面没有自己的map成员,而是把map放到在使用Thread类中。
而shaucle给出的自己threadLocal实现的例子里面拥有一个map,这个map会越来越大,所以还需要有另外的thread来定期清理map中thread已死的那些key
相关推荐
### Synchronized与ThreadLocal #### 一、Synchronized机制详解 **Synchronized** 是 Java 中一个非常重要的关键字,主要用于实现线程同步。它通过在对象上加锁来确保多个线程能够安全地访问共享资源。 - **作用...
ThreadLocal通常被用来解决线程共享数据时可能出现的并发问题,避免了使用synchronized关键字进行同步控制的复杂性。 在Java中,ThreadLocal的工作原理是为每个线程创建一个单独的存储空间,每个线程可以独立地读写...
**线程局部变量(ThreadLocal)是Java编程中一个非常重要的工具类,它在多线程环境下提供了线程安全的数据存储。ThreadLocal并不是一个变量,而是一个类,它为每个线程都创建了一个独立的变量副本,使得每个线程都...
在 `LeakingServlet` 的 `doGet` 方法中,如果 `ThreadLocal` 没有设置值,那么会创建一个新的 `MyCounter` 并设置到 `ThreadLocal` 中。关键在于,一旦 `MyCounter` 被设置到 `ThreadLocal`,那么它将与当前线程...
理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal
应优先考虑其他同步机制,如`synchronized`关键字或`java.util.concurrent`包中的工具类。 2. **及时清理**:确保在不再使用ThreadLocal时调用`remove()`,以防止内存泄漏。 3. **谨慎使用在长生命周期线程中**:如...
ThreadLocal 整理 ThreadLocal 是 Java 中的一个重要组件,它能够在每个线程中保持独立的副本。这个功能是通过 Thread 类中的 threadLocals 属性来实现的,这个属性实际上是一个 Entry 数组,其中的每个 Entry 都...
### 正确理解ThreadLocal:深入解析其工作原理与应用场景 #### 一、ThreadLocal的基本概念 `ThreadLocal`是Java平台提供的一种线程局部变量的解决方案,它为每一个使用该变量的线程都提供了独立的变量副本,使得每...
Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,尤其在处理线程间数据隔离和共享时。ThreadLocal不是线程本身,而是为每个线程提供一个独立的变量副本,使得每个线程都可以独立地改变...
Java事务和ThreadLocal是两种在Java编程中至关重要的概念,它们分别用于处理多线程环境下的数据一致性问题和提供线程局部变量。 首先,我们来深入理解Java事务。在数据库操作中,事务是一系列操作的集合,这些操作...
### Java中ThreadLocal详解 #### 一、ThreadLocal概述 在Java多线程编程中,`ThreadLocal`是一个非常重要的工具类,它提供了一种在每个线程内部存储线程私有实例的方法。通常情况下,当多个线程共享某个变量时,...
ThreadLocal是Java编程中一种非常特殊的变量类型,它主要用于在多线程环境下为每个线程提供独立的变量副本,从而避免了线程间的数据共享和冲突。然而,ThreadLocal在理解和使用过程中容易产生一些误区,这里我们将...
需要重点强调的的是,不要拿ThreadLocal和synchronized做类比,因为这种比较压根是无意义的!sysnchronized是一种互斥同步机制,是为了保证在多线程环境下对于共享资源的正确访问。而ThreadLocal从本质上讲,无非...
**线程局部变量(ThreadLocal)** 在Java编程中,`ThreadLocal`是一个非常重要的工具类,它用于在多线程环境中提供线程安全的局部变量。`ThreadLocal`并不是一个线程,而是一个线程局部变量的容器,每个线程都有自己...
本资料主要聚焦于两种设计模式以及Java中的ThreadLocal特性。 首先,我们来探讨单例模式。单例模式是一种确保一个类只有一个实例,并提供全局访问点的设计模式。在Java中,通常通过私有构造函数、静态工厂方法或...
学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!