聚合全网技术文章,根据你的阅读喜好进行个性推荐
threadlocal的出现并不是为了解决线程安全的问题
给你取这样一个典型的例子吧,你可以看到TLS实际的应用场合。在一个支持单进程,多线程的轻量级移动平台中,假设我实现了一个APP Framework,每一个APP单独运行在一个独立的线程中,APP运行时关联了很多信息,比如打开的文件,引用的组件,启动的Timer等等。我希望框架能实现自动垃圾回收,什么概念,就会应用退出的时候,即便应用没有主动释放打开的文件句柄,没有主动cancel Timer,没有主动释放组件的引用,框架也可以自动完成这些收尾工作,否则,后果是不堪想象的。 好了,假设应用的退出是调用了框架的 ExitApp API, 该API允许应用调用后关闭自己,也允许关闭别的应用。 那么,假设该API触发了应用的退出,最终调用到框架的App_CleanUp函数,那么App_CleanUp函数除了完成应用本身实例的释放外,肯定是在这里来完成我们上面说的收尾工作,怎么来做哪?! 很明显,这里典型的,就可以使用TLS了。具体如下:在Framework的API中,当应用的线程启动时,New 一个AppContext的对象或者结构体,然后将对象的指针或者结构体的指针以TLS的方式存储起来。 AppContext内部包含了文件句柄,timer引用,组件引用等等。 然后,后续任何框架的文件操作/Timer操作时,取当前线程的TLS,然后转换成AppContext后,将更新的文件句柄,timer引用等更新入AppContext对象内部。 然后,应用退出时,获取TLS,然后转换成AppContext,取出非空的文件句柄,组件引用,Timer引用等,来完成Cancel和Close操作。其他不想说了,如果你能明白这个实际的例子,你就可以明白TLS的用途了。 上述的例子,来源于BREW/BMP框架内部的实际实现,当然有差别,但是思想是一样的
对TLS更简单的,但是更直观的理解可以如下(基于C语言):1. 全局对象,全局变量的作用域和生命周期是全局的,这里的全局是指进程范畴,也就是说,如果你将其设计为全局对象,全局变量,就意味着你希望在多线程的环境中,仍然能共享和访问。 全局对象,全局变量不是说不让多线程来访问,而是说有的时候不期望他们同时访问,此时引入了线程的互斥,互斥的后果是保证不同时访问,但是,并没有改变共享的本质!2. 如果设计的时候,就希望将某个对象,变量设计为线程局部的,那典型的是可以将其设计为函数的局部变量。 可是,我如果又希望在线程执行时,任意的函数和对象里面都可以访问到它那?! 此时,可能会想到用全局对象,全局变量,但是,它又会使得这种访问域上升到进程级别,其实,我只是想在线程局部环境中,全局访问该对象。 此时TLS应运而生,TLS就是达到了这种, 在线程局部环境(或者称呼为线程执行环境,线程上下文)下可以全局访问的对象/变量。关于TLS的实际应用,更多的是定义一个TLS对象来存储一些线程上下文相关的信息。
TLS更多的是用来存储线程上下文相关的信息,使得在一致的代码中,自动访问差异性的线程绑定的上下文相关信息
不要由于java混淆了本质,其实就是TLS的概念,去问问搞linux的前辈,TLS的目的是为了线程同步和互斥?完全不能的概念
@相见欢 还有刚才我看了一下Threadlocal的源码,里面已经没有了Threadlocalmap,取而代之的是Values静态类,我的JDK是最新的JDK7u15,Threadlocalmap估计是JDK6的?
而且重点的threadlocalhashcode你也是没有讲到,剖根问底不深,往祖坟上刨刨
ThreadLocalMap 是Thread 对象的属性,会随着Thread 对象的回收而回收,但是很多容器都有线程池,我们很多时候还需要手动移除!
评论删除后,数据将无法恢复
引用来自“夕水溪下”的评论
ThreadLocalMap 是Thread 对象的属性,会随着Thread 对象的回收而回收,但是很多容器都有线程池,我们很多时候还需要手动移除!引用来自“WinWill2012”的评论
楼主理解得好像有点点问题,建议大家去看看这篇文章吧 http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8%A7%A3%E5%AF%86ThreadLocal/ 比较深入详细地介绍了ThreadLocal的实现原理,并讨论了ThreadLocal到底会不会引发内存泄露。引用来自“夕水溪下”的评论
ThreadLocalMap 是Thread 对象的属性,会随着Thread 对象的回收而回收,但是很多容器都有线程池,我们很多时候还需要手动移除!引用来自“WinWill2012”的评论
楼主理解得好像有点点问题,建议大家去看看这篇文章吧 http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8%A7%A3%E5%AF%86ThreadLocal/ 比较深入详细地介绍了ThreadLocal的实现原理,并讨论了ThreadLocal到底会不会引发内存泄露。引用来自“夕水溪下”的评论
ThreadLocalMap 是Thread 对象的属性,会随着Thread 对象的回收而回收,但是很多容器都有线程池,我们很多时候还需要手动移除!分析了ThreadLocal的实现原理以及是否会出现内存泄露
引用来自“wf2030”的评论
引用来自“相见欢”的评论
引用来自“wf2030”的评论
threadlocal的出现并不是为了解决线程安全的问题
我们想想线程安全是是什么?
多线程并发访问共享资源,对共享资源造成的读写不一致,是为了解决这个问题才出现的线程安全的问题,说到底,是都要对共享资源读写。
现在这个threadlocal为每个线程搞了一个副本(相当于在每个线程内部加了一个变量,当然threadlocal与局部变量还是不一样的,这里就不讨论这个问题了,暂且先允许我这么说吧),读写操作与其他线程无关,这跟多线程都要读取同一资源毛关系都没有。
假如x初始为10,线程A读取x为10,设置其为20,B又来了,读到的又是10,现在“安全”是“安全”了,但是对于共享资源x(注意这里说的是“共享”),现在B要的就是最后一个线程修改后的x的值,你给我一个之前我自己设置的值,有什么用呢?
引用来自“eastwake”的评论
给你取这样一个典型的例子吧,你可以看到TLS实际的应用场合。
在一个支持单进程,多线程的轻量级移动平台中,假设我实现了一个APP Framework,每一个APP单独运行在一个独立的线程中,APP运行时关联了很多信息,比如打开的文件,引用的组件,启动的Timer等等。我希望框架能实现自动垃圾回收,什么概念,就会应用退出的时候,即便应用没有主动释放打开的文件句柄,没有主动cancel Timer,没有主动释放组件的引用,框架也可以自动完成这些收尾工作,否则,后果是不堪想象的。
好了,假设应用的退出是调用了框架的 ExitApp API, 该API允许应用调用后关闭自己,也允许关闭别的应用。 那么,假设该API触发了应用的退出,最终调用到框架的App_CleanUp函数,那么App_CleanUp函数除了完成应用本身实例的释放外,肯定是在这里来完成我们上面说的收尾工作,怎么来做哪?! 很明显,这里典型的,就可以使用TLS了。具体如下:
在Framework的API中,当应用的线程启动时,New 一个AppContext的对象或者结构体,然后将对象的指针或者结构体的指针以TLS的方式存储起来。 AppContext内部包含了文件句柄,timer引用,组件引用等等。 然后,后续任何框架的文件操作/Timer操作时,取当前线程的TLS,然后转换成AppContext后,将更新的文件句柄,timer引用等更新入AppContext对象内部。 然后,应用退出时,获取TLS,然后转换成AppContext,取出非空的文件句柄,组件引用,Timer引用等,来完成Cancel和Close操作。
其他不想说了,如果你能明白这个实际的例子,你就可以明白TLS的用途了。 上述的例子,来源于BREW/BMP框架内部的实际实现,当然有差别,但是思想是一样的
引用来自“wf2030”的评论
引用来自“相见欢”的评论
引用来自“夕水溪下”的评论
引用来自“wf2030”的评论
引用来自“相见欢”的评论
引用来自“wf2030”的评论
threadlocal的出现并不是为了解决线程安全的问题
我们想想线程安全是是什么?
多线程并发访问共享资源,对共享资源造成的读写不一致,是为了解决这个问题才出现的线程安全的问题,说到底,是都要对共享资源读写。
现在这个threadlocal为每个线程搞了一个副本(相当于在每个线程内部加了一个变量,当然threadlocal与局部变量还是不一样的,这里就不讨论这个问题了,暂且先允许我这么说吧),读写操作与其他线程无关,这跟多线程都要读取同一资源毛关系都没有。
假如x初始为10,线程A读取x为10,设置其为20,B又来了,读到的又是10,现在“安全”是“安全”了,但是对于共享资源x(注意这里说的是“共享”),现在B要的就是最后一个线程修改后的x的值,你给我一个之前我自己设置的值,有什么用呢?
确实是这个意思,就是说既然要共享一份资源,肯定是希望他是唯一的,所以这个问题也许是线程安全和线程同步的关系。。。
引用来自“相见欢”的评论
引用来自“夕水溪下”的评论
引用来自“wf2030”的评论
引用来自“相见欢”的评论
引用来自“wf2030”的评论
threadlocal的出现并不是为了解决线程安全的问题
我们想想线程安全是是什么?
多线程并发访问共享资源,对共享资源造成的读写不一致,是为了解决这个问题才出现的线程安全的问题,说到底,是都要对共享资源读写。
现在这个threadlocal为每个线程搞了一个副本(相当于在每个线程内部加了一个变量,当然threadlocal与局部变量还是不一样的,这里就不讨论这个问题了,暂且先允许我这么说吧),读写操作与其他线程无关,这跟多线程都要读取同一资源毛关系都没有。
假如x初始为10,线程A读取x为10,设置其为20,B又来了,读到的又是10,现在“安全”是“安全”了,但是对于共享资源x(注意这里说的是“共享”),现在B要的就是最后一个线程修改后的x的值,你给我一个之前我自己设置的值,有什么用呢?
在一个支持单进程,多线程的轻量级移动平台中,假设我实现了一个APP Framework,每一个APP单独运行在一个独立的线程中,APP运行时关联了很多信息,比如打开的文件,引用的组件,启动的Timer等等。我希望框架能实现自动垃圾回收,什么概念,就会应用退出的时候,即便应用没有主动释放打开的文件句柄,没有主动cancel Timer,没有主动释放组件的引用,框架也可以自动完成这些收尾工作,否则,后果是不堪想象的。
好了,假设应用的退出是调用了框架的 ExitApp API, 该API允许应用调用后关闭自己,也允许关闭别的应用。 那么,假设该API触发了应用的退出,最终调用到框架的App_CleanUp函数,那么App_CleanUp函数除了完成应用本身实例的释放外,肯定是在这里来完成我们上面说的收尾工作,怎么来做哪?! 很明显,这里典型的,就可以使用TLS了。具体如下:
在Framework的API中,当应用的线程启动时,New 一个AppContext的对象或者结构体,然后将对象的指针或者结构体的指针以TLS的方式存储起来。 AppContext内部包含了文件句柄,timer引用,组件引用等等。 然后,后续任何框架的文件操作/Timer操作时,取当前线程的TLS,然后转换成AppContext后,将更新的文件句柄,timer引用等更新入AppContext对象内部。 然后,应用退出时,获取TLS,然后转换成AppContext,取出非空的文件句柄,组件引用,Timer引用等,来完成Cancel和Close操作。
其他不想说了,如果你能明白这个实际的例子,你就可以明白TLS的用途了。 上述的例子,来源于BREW/BMP框架内部的实际实现,当然有差别,但是思想是一样的
引用来自“eastwake”的评论
对TLS更简单的,但是更直观的理解可以如下(基于C语言):
1. 全局对象,全局变量的作用域和生命周期是全局的,这里的全局是指进程范畴,也就是说,如果你将其设计为全局对象,全局变量,就意味着你希望在多线程的环境中,仍然能共享和访问。 全局对象,全局变量不是说不让多线程来访问,而是说有的时候不期望他们同时访问,此时引入了线程的互斥,互斥的后果是保证不同时访问,但是,并没有改变共享的本质!
2. 如果设计的时候,就希望将某个对象,变量设计为线程局部的,那典型的是可以将其设计为函数的局部变量。 可是,我如果又希望在线程执行时,任意的函数和对象里面都可以访问到它那?! 此时,可能会想到用全局对象,全局变量,但是,它又会使得这种访问域上升到进程级别,其实,我只是想在线程局部环境中,全局访问该对象。 此时TLS应运而生,TLS就是达到了这种, 在线程局部环境(或者称呼为线程执行环境,线程上下文)下可以全局访问的对象/变量。
关于TLS的实际应用,更多的是定义一个TLS对象来存储一些线程上下文相关的信息。
1. 全局对象,全局变量的作用域和生命周期是全局的,这里的全局是指进程范畴,也就是说,如果你将其设计为全局对象,全局变量,就意味着你希望在多线程的环境中,仍然能共享和访问。 全局对象,全局变量不是说不让多线程来访问,而是说有的时候不期望他们同时访问,此时引入了线程的互斥,互斥的后果是保证不同时访问,但是,并没有改变共享的本质!
2. 如果设计的时候,就希望将某个对象,变量设计为线程局部的,那典型的是可以将其设计为函数的局部变量。 可是,我如果又希望在线程执行时,任意的函数和对象里面都可以访问到它那?! 此时,可能会想到用全局对象,全局变量,但是,它又会使得这种访问域上升到进程级别,其实,我只是想在线程局部环境中,全局访问该对象。 此时TLS应运而生,TLS就是达到了这种, 在线程局部环境(或者称呼为线程执行环境,线程上下文)下可以全局访问的对象/变量。
关于TLS的实际应用,更多的是定义一个TLS对象来存储一些线程上下文相关的信息。
引用来自“eastwake”的评论
TLS更多的是用来存储线程上下文相关的信息,使得在一致的代码中,自动访问差异性的线程绑定的上下文相关信息
而TLS究竟是解决什么问题那? TLS解决了这样一个需求,就是希望在一个/每个线程的线程上下文/环境下执行的任何实体(函数,组件等)内,都能访问某一个变量。 那么很明显,这个变量是需要做成全局的,但是,普通全局的会污染别的线程。所以,此时需要TLS。 举个最简单的例子,假设我的程序会连续启动6个线程去创建文件,线程代码是完全一样的。那么,我就可以使用TLS来记录线程上下文中的文件句柄。此时,我使用一致的文件操作代码,却能保证不管在任何实体中操作的文件句柄,都自动的是当前线程下的打开文件的文件句柄
引用来自“eastwake”的评论
不要由于java混淆了本质,其实就是TLS的概念,去问问搞linux的前辈,TLS的目的是为了线程同步和互斥?完全不能的概念
引用来自“wf2030”的评论
@相见欢 还有刚才我看了一下Threadlocal的源码,里面已经没有了Threadlocalmap,取而代之的是Values静态类,我的JDK是最新的JDK7u15,Threadlocalmap估计是JDK6的?
引用来自“相见欢”的评论
引用来自“夕水溪下”的评论
引用来自“wf2030”的评论
引用来自“相见欢”的评论
引用来自“wf2030”的评论
threadlocal的出现并不是为了解决线程安全的问题
我们想想线程安全是是什么?
多线程并发访问共享资源,对共享资源造成的读写不一致,是为了解决这个问题才出现的线程安全的问题,说到底,是都要对共享资源读写。
现在这个threadlocal为每个线程搞了一个副本(相当于在每个线程内部加了一个变量,当然threadlocal与局部变量还是不一样的,这里就不讨论这个问题了,暂且先允许我这么说吧),读写操作与其他线程无关,这跟多线程都要读取同一资源毛关系都没有。
假如x初始为10,线程A读取x为10,设置其为20,B又来了,读到的又是10,现在“安全”是“安全”了,但是对于共享资源x(注意这里说的是“共享”),现在B要的就是最后一个线程修改后的x的值,你给我一个之前我自己设置的值,有什么用呢?
确实是这个意思,就是说既然要共享一份资源,肯定是希望他是唯一的,所以这个问题也许是线程安全和线程同步的关系。。。
引用来自“相见欢”的评论
引用来自“aahuihui2010”的评论
引用来自“相见欢”的评论
引用来自“aahuihui2010”的评论
而且重点的threadlocalhashcode你也是没有讲到,剖根问底不深,往祖坟上刨刨
引用来自“aahuihui2010”的评论
引用来自“相见欢”的评论
引用来自“aahuihui2010”的评论
而且重点的threadlocalhashcode你也是没有讲到,剖根问底不深,往祖坟上刨刨
引用来自“相见欢”的评论
引用来自“aahuihui2010”的评论
而且重点的threadlocalhashcode你也是没有讲到,剖根问底不深,往祖坟上刨刨
引用来自“aahuihui2010”的评论
而且重点的threadlocalhashcode你也是没有讲到,剖根问底不深,往祖坟上刨刨
引用来自“wf2030”的评论
threadlocal的出现并不是为了解决线程安全的问题
引用来自“夕水溪下”的评论
ThreadLocalMap 是Thread 对象的属性,会随着Thread 对象的回收而回收,但是很多容器都有线程池,我们很多时候还需要手动移除!