设计模式之单例模式读后思考(二)

    上篇:我复习了6大原则, 睡觉前还想了一阵子, 我分析了一下, 想要牢记这些原则, 就必须动手写一些项目

 学习地址: 左哥的blog

    我记得我学习6大原则看了一个月, 这次这个单例模式 只看了4天, 有一点推动力感觉还是可以的

    我自己的理解:

    单例模式,原文: 指的是一个类在整个应用中, 有且只有一种状态.

        本人理解: 类只有一个, 所有调用者拿到的都是这个类, 调用者的修改是阻塞的, 调用者的查询是非阻塞的,

        单例模的应用场景基本都是在是可变共享

    原文中有个让cpu飙升的测试单例的方法, TestSinglenton 这个测试方法 ,主要问题出在lock这个变量上, 在前面加上volatile这个变量, 保证可见性,

其实加了volatile cpu也会飙升, 但是结果可以及时打印出来

    但是没加的话结果卡住,原因是什么,lock这个变量没有了可见性, 我推断lock.isLock()一直拿的是false, 所有的子线程一直没有获取到新的lock导致一直在循环

这时我就有个疑问了, 理论上在主线程我们改变lock的值, 但是这里显然, 子线程依然没有获取到我们想要的那个值, 难道说, lock之前的值依然没有被gc掉 

我加了一小段代码检验的一番

while (true) {
System.out.println("----"+lock.isLock()+"1------");
System.out.println("----"+lock.isLock()+"2------");
System.out.println("----"+lock.isLock()+"3------");

.....
}

    结果,很震惊, 同一个线程下取到的lock值居然不一样, 并且 lock1总是初始值 lock3的数量>lock2, 这里感觉像 线程看着lock的值从true变成false 

    这5列代表5个线程

    

    一个渐渐变化的过程,  等看完jvm再详细分析一波, 实际上是不是这样的呢?

    终于, 我在java并发实战中找到了这个答案,

  

     但是在实际的我还是发现的一个问题, 如果我没有打印这个lock,

        ①那么lock.isLock始终拿的是true, 一直在循环

        ②也有可能是由于数据竞争问题导致了线程阻塞, 这里到底是堵塞了,还是状态未更改

    我使用jconsole 发现

  

      从上面看结论是: ① 线程一直拿的是true 一直在循环

  我也观察了内存使用状态

  

ps:这个工具是 jdk自带的工具, 路径:JAVA_HOME/bin/jconsole.exe

  其中 新生代 eden 一直在增长 , 很多网站上搜索出来都是说是, 你new了对象的过程, 这里我就我观察到的结果来说 , 不是这样的

我的观点: 由于线程一直在循环, 生成了很多的代码缓存, 这些代码缓存中的一些对象或者基本类型数据的替换 都会重复的生成在 新生代,

我手动调用了一下gc, 其他区域没有变动, 新生代降了很多,其他区域不受影响

  综上, 我得出一个结论:

            多个线程读取同一个变量并且至少被一个以上的线程修改时, 如果该变量没有被volatile或同步关键词修饰或者读取的线程没有对该变量进行流操作 这里后来给其他同事测试发现, 可能只需要这个线程涉及到流的操作,就可以,具体原因以后发现继续更新,       那么读取线程始终无法获取到修改后的变量值

  上面是我自己理解的有什么好的见解, 可以发到我的邮箱719285662@qq.com, 或者直接评价

好了单例模式告一段落,继续我的学习认证之路

        

posted @ 2017-01-19 18:44  hassenli  阅读(502)  评论(0编辑  收藏  举报