同步区域有点像拜访你的公公婆婆。你当然是希望待的时间越短越好。说到锁的话情况也是一样的,你希望获取锁以及进入临界区域的时间越短越好,这样才不会造成瓶颈。
synchronized关键字是语言层面的加锁机制,它可以用于方法以及代码块。这个关键字是由HotSpot JVM来实现的。我们在代码中分配的每一个对象,比如String, Array或者一个JSON文档,在GC的层面的对象头部,都内建了一个加锁的机制。JIT编译器也是类似的,它在进行字节码的编译和反编译的时候,都取决于特定的某个锁的具体的状态和竞争级别。
同步块的一个问题在于——进入临界区域内的线程不能超过一个。这对生产者消费者场景是一个很大的打击,尽管这里有些线程会尝试进行独占式的数据编辑,而另外一些线程只是希望读取一下数据,这个是可以和别的线程同时进行的。
读写锁(ReadWriteLock)是一个理想的解决方案。你可以指定哪些线程会阻塞别的操作(写线程),哪些线程可以和别人共同进行内容的消费(读线程)。一个美满的结局?恐怕不是。
读写锁不像同步块,它并不是JVM中内建支持的,它只不过是段普通的代码。同样的,要想实现锁机制,它得引导CPU原子地或者按某个特定的顺序来执行某些特定的操作,以避免竞争条件。这通常都是通过JVM预留的一个后门来实现的——unsafe类。读写锁使用的是CAS操作来将值直接设置到内存中去,这是它们线程排队算法中的一部分。
尽管这样,读写锁也还不够快,有时候甚至会表现得非常慢,慢到你压根儿就不应该使用它。然而JDK的这帮家伙们没有放弃治疗,现在他们带来了一个全新的StampedLock。这个读写锁使用了一组新的算法以及Java 8 JDK中引入的内存屏障的特性,这使得这个锁更高效也更健壮。
它兑现了自己的诺言了吗?让我们拭目以待。