本文为原创文章,转载请注明出处,谢谢你……
> 喜欢java并发编程的请加群:736156823
开始-->
很喜欢使用volatile关键字,还没有啥需要特殊关注的,平时用的也很嗨,但是最近通过反射修改了这个字段,发现了一些小问题,描述如下:
1.
初始化由spring管理这个字段在初始化时候由spring加载时候读取配置文件中的值通过反射设置进来,代码如下:
反射注入反射替换好后,打印结果:
debug这时直接打印是没有问题的,与properties文件中的值保持一致,立刻可见。这是由spring启动线程打印的。(代码最好不要挂火车,哈哈……)
2.所有初始化完毕后,会通过信号量的机制,提醒另一个线程打印结果,代码如下:
初始化代码 二值信号量与无用等待负责打印的另一个线程代码如下:
另一个打印线程 打印信息方法3.问题来了:
spring线程打印的结果是配置文件的值,但是打印线程的打印结果却是代码中的默认值……怪了……哈哈
下面本人解决办法与问题猜测(很不专业,哈哈……)。
解决:
打印方法上加锁这个方法简单好用(不好用)。
就刚才,我测试了下,刚开始使用lock还好使的。现在竟然不好使了,哈哈……好奇妙,如下图:
突然lock不好使了配置文件中配置的值是on,但是使用lock打印的结果却是off……哈哈,奇妙……
再启动的时候先通过spring反射修改掉,在spring中打印config类中的值是on,但是全部启动完后,通过信号量使用打印线程打印出的竟然是off,打印方法是带有lock的,这两部之间没有任何其余修改动作。
更奇妙的又来了,哈哈……
系统中有许多定时任务,任务中需要获得开关的值,但是,这些获取值的动作获取到的值竟然是全部正确的,哈哈……厉害……
定时任务获得正确值针对以上情况改动如下。
因为定时任务启动有延迟,那么我直接修改延迟时间为0,测试下:
修改后测试结果00 修改后测试结果01出现两个问题,配置文件中button全部是on,代码中button全部是off,第一个截图中既有on又有off,这个打印实在一个lock中的;第二,在定时器立即启动运行时原来打印为off的全部是on了,而且之后的全部值都是on。
小完结:
1.说下本人对volatile关键字的理解吧,哎……
添加缓存行失效标记……每次读取内存中的值,不使用线程本地缓存……每次修改完成会强制刷新回主存,那么谁来帮助刷新(这是我一直关注的问题)?操作系统总线机制帮忙刷新,至于什么时候刷新,刷新速度,每次刷新允许最小间隔是多少,不得而知,可以参考《计算机组成原理》,不同平台略有区别,况且jvm内存模型是怎么配合操作系统的我也不清楚。所以本人使用时候还没遇到过什么问题,只要知道哪里是关键就好了,其他的不要多想。
这次系统中需要一个功能就是对配置文件的热加载能够及时的反应到定时任务中,并且能够根据变换,立即修改定时间隔,重新启动定时,所以才有上面的问题出现。
2.正因为上面volatile关键字的特点所以才有上述的奇妙,但是本人的系统是异步的,不允许有阻塞或者说长时间阻塞,所以我在这里,仅仅是为了初始化时候打印正常,加了一短促等待:
短促等待至于对功能上的影响,还是比较少的,毕竟:1.定时延迟大于1秒;2.系统总线刷新缓存很快。所以,没有影响。
3.上述打印的地方仍然是使用lock的,现在不修改了。
4.关于打印方法:
延迟打印由于打印方法是异步调用,初始化线程是通过信号量触发其他线程打印的,所以都不会有阻塞,都是正常的执行过程,所以暂时都这样来修改了。
5.由于是热加载的,即时生效,所以我刚才修改了下配置文件,然后文件监控器通过信号量唤醒触发,结果如下:
测试热加载看吧,系统刷新还是很快的,哈哈……
6.所以,这样一来,没有理解volatile的朋友是不是理解了,所以,这个用起来还是不错的,毕竟操作系统还是可以的,哈哈……至于指令重排,对象的完整初始化保证等能力,大家还是自行百度吧
8.后续跟进seda模型
> 喜欢java并发编程的请加群:736156823
结束-->
本文为原创文章,转载请注明出处,谢谢你……
网友评论