• 关于JMM与DCL的知识点


    JMM中的关系总结:
    工作内存对应多核处理器中的每个处理器的高速缓存。主存对应的是内存。
    工作内存与主存的关系很象是分布式缓存与客户端的关系。堆的共享,是Java中线程通讯的基础。
    工作内存的变量是主存中变量的copy。
    工作内存的中的变量只有提交到主存才能被其它工作内存看到。

    volatile:

    volatile原理:不使用工作内存,而直接访问主存中的变量。适用的场景是经常变化的变量。这样就会保证每次读到的都是最新的内容。当然是牺牲了性能。
    volatile还有一个作用就是禁止JVM对代码优化(reorder)
    final与volatile的区别就是final是在构造方法执行完之后就不再改变。这也就不提供多线程修改的机会。当然是线程安全。但是,对于volatile,是提供多线程修改的机会的。只不过,直接操作主存。
    所以,一定要将final与线程联系起来看。而不要象满大街文章说如何提高性能。

    synchronized原理.
    修饰块:
    synchronized (obj){
      ......
    }
    obj可以是this,对象的一个属性。
    obj又被称为monitor.
    注意synchronized修改块方法的原理是一样的。只是修饰方法时,默认是以this为monitor.
    通常总是把monitor认为是lock。原理是synchronized获得monitor对象之后,会在monitor上加锁。monitor并不是锁。通常很容易在程序中定义obj的名字为**Lock.这是不恰当的。但是不影响使用。
    当针对monitor上锁之后,其它线程访问方法或代码块必须等上次操作给monitor解锁才行,解锁之后,其它线程才可以给monitor加锁并进一步访问。
    synchronzied修改静态方法时,被锁定对象是Object.class,而不再是this了。

    DCL的产生及解决:
    首先DCL产生的原因是单例中使用了延迟加载.
    即使针对对象使用volatile修饰,但是JVM仍然会对volatile与非volatile的属性reorder。估计除非全部是volatile属性才会避免reorder的问题。只要存在reorder,就有可能导致:“允许对象在构造函数未调用完前, 将共享变量的引用指向部分构造的对象, 虽然对象未完全实例化, 但已经不为null了”.
    所以如果只要单例不要延迟加载的话可以这样实现:
    class Singleton{
      private Vector v;
      private boolean inUse;
      //不做延迟加载来避免DCL。
      private static Singleton instance = new Singleton();

      private Singleton()
      {
        v = new Vector();
        inUse = true;
        //...
      }

      public static Singleton getInstance()
      {
        return instance;
      }
    }

    又要单例,又要延迟加载可以这样实现:内部类可以在引用的时候才加载。
    public class Foo {
        // 静态内部类, 只有当有引用时, 该类才会被装载
        private static class LazyFoo {
           public static Foo foo = new Foo();
        }

        public static Foo getInstance() {
           return LazyFoo.foo;
        }
    }
    如果又想单例,又延迟,又想多线程访问:
    public class Foo {
        private static class LazyFoo {
           public static Foo foo = new Foo();
        }

        public static synchronized Foo getInstance() {
           return LazyFoo.foo;
        }
    }

  • 相关阅读:
    sql2005事务的使用
    [原]using的另一种用法
    [原]Cache的简单用法
    [原] Js动态删除行(支持FireFox)
    [原]为什么文本框高度不一样?
    [原]如何把object解析为int,double,float?
    压缩SQL SERVER日志文件
    [原]替换的更新(Update)查询
    [原]让链接点击过后无虚线
    [原]取得Access表中表的名字
  • 原文地址:https://www.cnblogs.com/highriver/p/1821667.html
Copyright © 2020-2023  润新知