• yang
    2019-02-27
    1 通过采用java内存模型,保证多线程场景下共享资源的可见性
    2使用局部变量,可以减少主存与线程内存的拷贝次数
    3第一次是初始化,第二次是同步局部变量与属性变量的值,保持一致
    4第一次检查是为了快速获取对象,第二次检查是为了防止对象未初始化,就是标准的double check
    5是为了线程安全,同时高性能,锁范围更小化
    6前者是线程安全,后者是非线程安全
    7还是减少主存与线程内存值拷贝的开销
    个人理解,如有误,敬请指正
    展开

    作者回复: volatile的使用,需要一定程度的同步,也就是你说的拷贝开销。减少volatile变量的引用,可以提高效率。

    恭喜你,这些Java的难点你掌握的很扎实!

    
     19
  • 梦醒时分
    2019-02-27
    我的思考:
    1.volatile是用来保证变量的可见性的,这样其他线程才能及时看到变量的修改
    2.为啥要使用temporaryMap变量,这里没有想明白
    3.两次设置temporaryMap变量,目的是双重检查,防止进入同步代码块中,变量已被赋值了
    4.同上
    5.synchronized的使用是影响性能的,所有在使用它之前,先校验下是否需要进入同步块中
    6.ConcurrentHashMap是线程安全的,而HashMap不是线程安全的
    7.为啥使用temporaryMap.put不太清楚
    展开

    作者回复: 关于temporaryMap的使用,请参考@yang的留言。

    
     6
  • 拉可里啦
    2019-04-07
    作为类的全局变量而非静态变量,只能被类的实例所拥有,那么只有一个对象再操作这个全局变量,单线程操作这个变量不会有线程安全问题,多个线程同时操作这个变量有线程安全问题,是以对象为单位的。不知道我这样理解对不对,还请老师指点指点。

    作者回复: 是的,是以对象为单位的。 所以,你看Java的代码里,synchronized(this), this指的就是一个具体的对象。同一个类,实例化的对象不同,也不需要同步。

    
     3
  • 唐名之
    2019-03-01
    @yang回到第二点 使用局部变量,可以减少主存与线程内存的拷贝次数 这个点还是有点不明白能解释下嘛?
    
     2
  • Linuxer
    2019-02-28
    请问各位思考题中的volatile修饰后是不是就只能用concurrenthashmap?要不赋值给局部变量后主存和线程内存还是不同步

    作者回复: volatile修饰符和使用concurrent hash map关系不大。volatile修饰的是标志符,不是标志符指向的内容。

    
     2
  • Jxin
    2019-05-28
    1.类属性的调用和赋值全部走set和get方法。这种非静态且多次赋值的局部变量应该尽量避免。
    2.带锁初始化操作应该上移到get方法。至少从函数功能来看,我认为初始化应该是属于get的。
    3.我真不喜欢加锁和每次get都做判断,所以了解业务上下文,如果可以,我会直接给该属性做初始化。
    3.如果了解完上下文我对这个集合或则散列表的大小能有一定把我,我会尝试给定一个合适的初始化大小。

    作者回复: 👍都是很好的实践经验! 了解适用场景,是高效代码的关键。

    
     1
  • aguan(^・ェ・^)
    2019-03-06
    老师,我有一个疑问,思考题的代码,在多线程的情况下,如果第16行用tempHashmap.put,是会出现空指针的。因为cpu指令重排序,当线程1在执行new map的时候,可能cpu先给temp分配内存空间,对象还没实例化,这时候另外一个线程在第一个if的时候发现temp不为空(因为有地址,但地址里并没有实例化对象),接着去执行16行的代码,会出现空指针问题吧

    作者回复: tempHashmap是一个局部变量,不跨越线程。

    
     1
  • 鱼筱雨
    2019-08-29
    范老师,我总是有个疑惑,举个例子
    Map<String,String> m = new HashMap<>();
    在这段代码中,左边的泛型中会声明具体类型,而右边的泛型中往往是空的,而我在代码开发中右边的泛型都会和左边保持一致,这样做有什么问题吗?哪种更好一点?

    作者回复: 现在推荐使用的模式是声明时指定类型,使用时让编译器来自动匹配。对于上面的代码,也就是左边声明具体类型,而右边使用空指示符。这样做的主要目的是简化编码,避免不必要的失误和检验。

    
    
  • Jxin
    2019-06-10
    采用了临时变量,对象是否就失去了可视性和有序性的特性?这样在new操作时,由于虚拟机的编译优化,cpu时间片切换时不是可能会出现空指针报错吗?
    
    
  • aguan(^・ェ・^)
    2019-03-07
    恍然大悟,所以局部变量是解决双重检查重排序空指针问题的安全方法👍
    
    
  • 轻歌赋
    2019-03-02
    1.双检锁在多CPU情况下存在内存语义bug,通过volatile实现其内存语义
    2.单线程内存一致性语义
    3.多线程并发,存在一个线程先于其他线程设置值的情况
    4.多线程并发,检查helloworldsmap是否被其他线程赋值
    5.提高并发度
    6.代码体现这是一个多CPU多线程的环境,存在map被并发修改的情况,concurrenthashmap是线程安全的,而hashmap是线程不安全的所以使用前者
    7.不知道,感觉像是逻辑上比较顺
    展开
    
    
  • 多拉格·five
    2019-02-27
    这个就是类似于单例里边的双重检查写法吧
    
    
我们在线,来聊聊吧