zoukankan      html  css  js  c++  java
  • 8.30

    1.对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的

        synchronized(this)    synchronized void test2()   对象锁 当某个方法加上synchronized关键字后,就表明要获得该内置锁才能执行,并不能阻止其他线程访问不需要获得该内置锁的方法。

                 synchronized(TestSynchronized.class)    static synchronized void test2()                  类锁   此类所有实例化对象在调用此方法时候,共同用一把锁。

    对象锁是用来控制实例方法之间的同步,

    类锁是控制静态变量互斥。

    ------------------------------------------------------------------------

    Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

    1)、Bean自身的方法  :  这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法

    2)、Bean级生命周期接口方法  :  这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

    3)、容器级生命周期接口方法  :  这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

    4)、工厂后处理器接口方法  :  这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

    • Bean容器找到配置文件中Spring Bean的定义。
    • Bean容器利用Java Reflection API创建一个Bean的实例。
    • 如果涉及到一些属性值 利用set方法设置一些属性值。
    • 如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
    • 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
    • 如果Bean实现了BeanFactoryAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
    • 与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。
    • 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法
    • 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
    • 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。
    • 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessAfterInitialization()方法
    • 当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy()方法。
    • 当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。
    • Bean容器找到配置文件中Spring Bean的定义。
    • Bean容器利用Java Reflection API创建一个Bean的实例。
    • 如果涉及到一些属性值 利用set方法设置一些属性值。
    • 如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
    • 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
    • 如果Bean实现了BeanFactoryAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
    • 与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。
    • 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法
    • 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
    • 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。
    • 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessAfterInitialization()方法
    • 当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy()方法。
    • 当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。
    • -----------------------------------------------------
    • 定位Segment

      既然ConcurrentHashMap使用分段锁Segment来保护不同段的数据,那么在插入和获取元素的时候,必须先通过哈希算法定位到Segment。可以看到ConcurrentHashMap会首先使用Wang/Jenkins hash的变种算法对元素的hashCode进行一次再哈希。

       

      再哈希,其目的是为了减少哈希冲突,使元素能够均匀的分布在不同的Segment上,从而提高容器的存取效率。假如哈希的质量差到极点,那么所有的元素都在一个Segment中,不仅存取元素缓慢,分段锁也会失去意义。我做了一个测试,不通过再哈希而直接执行哈希计算。

    Segment的get操作实现非常简单和高效。先经过一次再哈希,然后使用这个哈希值通过哈希运算定位到segment,再通过哈希算法定位到元素,代码如下:

    get操作的高效之处在于整个get过程不需要加锁,除非读到的值是空的才会加锁重读,我们知道HashTable容器的get方法是需要加锁的,那么ConcurrentHashMap的get操作是如何做到不加锁的呢?原因是它的get方法里将要使用的共享变量都定义成volatile,如用于统计当前Segement大小的count字段和用于存储值的HashEntry的value。定义成volatile的变量,能够在线程之间保持可见性,能够被多线程同时读,并且保证不会读到过期的值,但是只能被单线程写(有一种情况可以被多线程写,就是写入的值不依赖于原值),在get操作里只需要读不需要写共享变量count和value,所以可以不用加锁。之所以不会读到过期的值,是根据Java内存模型的happen before原则,对volatile字段的写入操作先于读操作,即使两个线程同时修改和获取volatile变量,get操作也能拿到最新的值,这是用volatile替换锁的经典应用场景。

    ConcurrentHashMap的Put操作

    由于put方法里需要对共享变量进行写入操作,所以为了线程安全,在操作共享变量时必须得加锁。Put方法首先定位到Segment,然后在Segment里进行插入操作。插入操作需要经历两个步骤,第一步判断是否需要对Segment里的HashEntry数组进行扩容,第二步定位添加元素的位置然后放在HashEntry数组里。

    是否需要扩容。在插入元素前会先判断Segment里的HashEntry数组是否超过容量(threshold),如果超过阀值,数组进行扩容。值得一提的是,Segment的扩容判断比HashMap更恰当,因为HashMap是在插入元素后判断元素是否已经到达容量的,如果到达了就进行扩容,但是很有可能扩容之后没有新元素插入,这时HashMap就进行了一次无效的扩容。

    如何扩容。扩容的时候首先会创建一个两倍于原容量的数组,然后将原数组里的元素进行再hash后插入到新的数组里。为了高效ConcurrentHashMap不会对整个容器进行扩容,而只对某个segment进行扩容。

  • 相关阅读:
    BZOJ 3506 机械排序臂 splay
    BZOJ 2843 LCT
    BZOJ 3669 魔法森林
    BZOJ 2049 LCT
    BZOJ 3223 文艺平衡树 splay
    BZOJ 1433 假期的宿舍 二分图匹配
    BZOJ 1051 受欢迎的牛 强连通块
    BZOJ 1503 郁闷的出纳员 treap
    BZOJ 1096 ZJOI2007 仓库设计 斜率优化dp
    BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
  • 原文地址:https://www.cnblogs.com/yangchunchun/p/7451684.html
Copyright © 2011-2022 走看看