- 浏览: 39942 次
- 性别:
- 来自: 深圳
-
最新评论
-
shuaiji:
有点看不懂呢
JAVA序列化基础知识Serializable与Externalizable的区别 -
nepalon:
LZ写的在getCount和setCount中用synchro ...
ThreadLocal and synchronized 补充 -
ecoll:
两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的 ...
ThreadLocal and synchronized 补充 -
max.h.chen:
klyuan 写道保护数据的一致性ThreadLocal会更好 ...
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
相关推荐
总结以上内容,可以得出Java技术开发中需要掌握的诸多关键知识点,包括线程同步机制(synchronized与Lock)、线程本地存储(ThreadLocal)、原子操作(atomic)、类加载机制、远程方法调用(RMI)、框架使用经验...
2024年第一季度,青岛房地产市场经历了显著变化,总体呈现供需双降的趋势。一季度全市商品房新增10,721套,面积约152.04万平方米,同比下降29%;销量为14,936套,面积约200.85万平方米,同比下降38%,成交均价为14,204元/平方米,同比下降2%。土地市场方面,供应总量为39万平方米,同比减少7%,但成交面积为27万平方米,同比增长31%,楼面地价为6,625元/平方米,同比增长253%,土地出让金为17.61亿元,同比增长354%。二手房市场新增挂牌2.9万套,成交13,405套,132.21万平方米,累计挂牌51.70万套,挂牌均价17,800元/平方米。此外,青岛市出台多项政策支持房地产市场平稳健康发展,包括降低房贷利率、优化开发用地土地规划政策、支持房企融资等。这些政策旨在促进市场供需平衡,防止市场大起大落。
linux常用命令大全
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
空调销售网站策划案例.doc
全球6G技术大会2024年以用户为中心的6G接入网技术研究白皮书31页.pdf
简约专业风格毕业答辩模板是一系列专为追求简洁与高效表达的大学生设计的答辩文档模板,共47个。这些模板融合了经典的设计元素与现代审美,强调信息的清晰传递与视觉的整洁,旨在帮助学生在答辩中以最专业的面貌展示自己的研究成果。 每个模板都具备结构合理的布局,适用于各个学科和研究领域,从人文社科到自然科学,均能满足不同需求。简约风格的设计使得学生能够专注于内容本身,避免冗余信息的干扰,提升答辩的专业性和可信度。此外,模板中合理运用的色彩、字体和图表设计,不仅增强了视觉吸引力,也使信息更易于理解。 通过使用这些简约专业风格的毕业答辩模板,毕业生能够自信地呈现自己的学术成果,提升答辩的整体效果,为成功的学术交流打下坚实基础。这些模板是展示个人研究与风格的理想选择。
由 Epsilon Luoo 在 HC3-Chinese 的基础上进行了一些细微的修改和清洗
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 你是否渴望高效解决复杂的数学计算、数据分析难题?MATLAB 就是你的得力助手!作为一款强大的技术计算软件,MATLAB 集数值分析、矩阵运算、信号处理等多功能于一身,广泛应用于工程、科学研究等众多领域。 其简洁直观的编程环境,让代码编写如同行云流水。丰富的函数库和工具箱,为你节省大量时间和精力。无论是新手入门,还是资深专家,都能借助 MATLAB 挖掘数据背后的价值,创新科技成果。别再犹豫,拥抱 MATLAB,开启你的科技探索之旅!
HI3519DV500 配置无线网依赖库以及编译脚本
资源说明; 1-----刷写前提是手机必须解锁bl先。而且会在fast模式刷写固件 2-----刷写方法与官方刷写步骤一样 3-----此固件为定制初始固件。可以在fast模式刷写 4-----属于适配固件。也许有个别bug。不接受请勿下载 5-----需要一定的刷机常识与动手能力的友友刷写。 6-----资源有可复制性。下载后不支持退。请知悉 7-----定制其他需求可以在csdn私信博主 博文参阅:https://csdn9.blog.csdn.net/article/details/143058308
Matlab领域上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
世邦魏理仕:2021年西安房地产市场回顾与2022年展望
Android Studio 2022.1.1和java编程语言yinyuebofangqi
C知道对话分享图片
png-jpg-gif-webp-tiff等图片压缩工具基于nodejs的实现,绿色本地免安装,解压后运行exe文件,将图片文件或者包含图片的文件夹拖拽到软件界面即可压缩
我们要了解什么是DSP(Digital Signal Processing)。DSP即数字信号处理,是一种利用数字计算方法对信号进行分析、变换和操作的技术。在汽车音响领域,DSP被广泛应用于改善音质,通过调整频率响应、延时、相位和增益等参数,使声音更加均衡、立体。 惠威是一款数字信号处理器,适用于那些希望升级原车音响系统但预算有限的用户。它通常拥有多个输入和输出接口,可以连接到汽车的音频源和扬声器,通过软件进行调音,使得声音能够适应不同的驾驶环境和听音偏好。 ,集成了先进的噪声抑制技术和强大的功率放大器,旨在为发烧友级别的车载音响系统提供卓越的性能。用户可以通过软件对整个系统的每一个细节进行优化,包括主动分频、时间校正等,以达到Hi-Fi级别的音乐享受。
通信工程分包合同.docx
demo1(1).py
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 你是否渴望高效解决复杂的数学计算、数据分析难题?MATLAB 就是你的得力助手!作为一款强大的技术计算软件,MATLAB 集数值分析、矩阵运算、信号处理等多功能于一身,广泛应用于工程、科学研究等众多领域。 其简洁直观的编程环境,让代码编写如同行云流水。丰富的函数库和工具箱,为你节省大量时间和精力。无论是新手入门,还是资深专家,都能借助 MATLAB 挖掘数据背后的价值,创新科技成果。别再犹豫,拥抱 MATLAB,开启你的科技探索之旅!