锁之编程细节

前言

关于Java锁细节的博客,蛮受读者欢迎的。也有许多不足,好比排版,一些细节等。Java锁细节与锁之编程细节讲述锁的两个不一样方面,因此分开写。Java锁细节是讲述每种锁的细节,把锁当作人的话,讲述的是男人,女人,大人,小孩的细节。锁之编程细节讲述的如高性能的使用锁。如同让人怎么跑得块而已。java

大纲

编程细节以下:算法

  1. 锁粗化
  2. 锁细化
  3. 保证public方法线程安全
  4. 分段锁

主体

关于锁粗化与锁细化,在不少关于java优化的书籍都会讲解。好比java并发编程(是老胡并发与锁的启蒙书)等等。一些读者在读Java锁细节说没有讲解锁粗化。在你们的要求,老胡只能厚着面皮写下本博客了。编程

你们是否以为十分绕口,锁粗化,锁细化在名词上是两个对立的。为何都是优化的方法了?其实能够想象成长跑,短跑。就行了。api

锁粗化

  1. 把屡次的锁合并成一个锁,减小锁消耗,提高执行性能
  2. 在高并发的状况下,减小锁竞争。

receiveIntegerNoLock 方法调用了两个声明synchronized的方法。数组

public  IntegeralInfo receiveIntegerNoLock(Integer addIntegeral) {
	    addIntegeral(addIntegeral);
	    addReceiveNum();
	    return this;
	}

	/**
	 * 增长积分
	 * 
	 * @param addIntegeral
	 */
	public synchronized void addIntegeral(Integer addIntegeral) {
	    this.integeralValue += addIntegeral;
	}

	/**
	 * 增长签到次数
	 */
	public synchronized void addReceiveNum() {
	    this.receiveNum++;
	}

新的receiveInteger方法声明了synchronized。值使用了一个锁安全

public synchronized IntegeralInfo receiveInteger(Integer addIntegeral) {
	    this.integeralValue += addIntegeral;
	    this.receiveNum++;
	    return this;
}

锁细化

  1. 只对须要数据安全的操做上锁。减小锁占用时间。从而提高并发性能
  2. 使用。vm会对进行优化。锁范围为少,优化越好

需求,经过连续签到的天数,计算当次签到应获得多少积分,把计算出的积分增长到用户积分上,并计算除等级。并发

分析以下高并发

  1. 须要经过连续签到天数,计算当次签到应获得多少积分
  2. 把计算出的积分增长到用户积分上
  3. 并计算除等级
案例
public synchronized void continuityReceiveIntegeralAlsoGradeSynchronized(Integer continuityDate) {
	    // 经过天数计算,应该得到多少积分
	    int addIntegeral = calculationSignIntegeral(continuityDate);
	    // 添加积分
	    this.integeralValue += addIntegeral;
	    // 计算等级
	    gradeCalculation();
	}
		public int calculationSignIntegeral(Integer continuityDate) {
	    return continuityDate/1;
	}
	/**
	 * 等级计算
	 */
	private void gradeCalculation() {

	}

最简单的实现,没有进行任何的优化。三个操做的代码放到一个方法里面。观察calculationSignIntegeral方法会发现,只是进行数据计算,是一个安全的方法,能够不用上锁。gradeCalculation方法在必定程度上也是安全的方法,未实现。这个需求有点复杂,不知道那个大神,能够分析出来,并实现。性能

优化以后的是
public void continuityReceiveIntegeralAlsoGrade(Integer continuityDate) {
			// 经过天数计算,应该得到多少积分
			int addIntegeral = calculationSignIntegeral(continuityDate);
			// 添加积分
			synchronized (this) {
					this.integeralValue += addIntegeral;
			}
			// 计算等级
			gradeCalculation();
	}

只对须要上锁的计算出的积分增长到用户积分上操做进行上锁,减小的上锁范围。缩短持有锁的时间,从而提升并发性能学习

public都是线程安全

java api里面的类,个个都写得十分优秀。是学习,深刻,理解基础技术的优质的代码。解读java.util.Hashtable的源码,从而理解public都是线程安全,而非public方法都是线程不安全的。当你看完java.util.Hashtable源码会发现,全部的public都是线程安全,而非public方法都是线程不安全的。

public都是线程安全,而非public方法都是线程不安全的。这种设计有一下特性

  1. 一种优秀的编码规范,方法层次十分明显,强大的可读性。减小开发成本,维护成本,理解成本,容易定位问题。
  2. 全部public方法的实现只能为锁粗化。
  3. public方法内没有具体的实现,只负责调用private方法。private负责具体的实现。这是一种开闭原则的具体实现。

开闭原则(OCP)是面向对象设计中“可复用设计”的基石,是面向对象设计中最重要的原则之一,其它不少的设计原则都是实现开闭原则的一种手段。对于扩展是开放的,对于修改是关闭的,这意味着模块的行为是能够扩展的

分段锁

按照算法计算出的结果或者数据特性进行分类,分类中的每一个类型都有一把锁。能够减小锁争夺,更高并行度

关于分段锁最简单的实现仍是在java api中,jdk6的ConcurrentHashMap。 ConcurrentHashMap经过hash算法获得key的hash值,在与数组长度求余,余数是数组下标。下标就是分类的类型 下面连接是一个大神写的关于jdk6的ConcurrentHashMap源码解读,写得有点乱,可是解读得十分详细。请点击

完整代码

public class LockUser {

    static class IntegeralInfo {
	// 用户积分
	private Integer integeralValue;

	// 经验值
	private Integer experienceValue;

	// 签到
	private Integer receiveNum;

	// 等级
	private Integer grade;

	/**
	 * 添加积分,同时增长签到次数
	 * 
	 * @param addIntegeral
	 *            须要添加的积分
	 * @return
	 */
	public synchronized IntegeralInfo receiveInteger(Integer addIntegeral) {
	    this.integeralValue += addIntegeral;
	    this.receiveNum++;
	    return this;
	}
	
	public  IntegeralInfo receiveIntegerNoLock(Integer addIntegeral) {
	    addIntegeral(addIntegeral);
	    addReceiveNum();
	    return this;
	}

	/**
	 * 增长积分
	 * 
	 * @param addIntegeral
	 */
	public synchronized void addIntegeral(Integer addIntegeral) {
	    this.integeralValue += addIntegeral;
	}

	/**
	 * 增长签到次数
	 */
	public synchronized void addReceiveNum() {
	    this.receiveNum++;
	}

	public synchronized void continuityReceiveIntegeralAlsoGradeSynchronized(Integer continuityDate) {
	    // 经过天数计算,应该得到多少积分
	    int addIntegeral = calculationSignIntegeral(continuityDate);
	    // 添加积分
	    this.integeralValue += addIntegeral;
	    // 计算等级
	    gradeCalculation();
	}

	public void continuityReceiveIntegeralAlsoGrade(Integer continuityDate) {
	    // 经过天数计算,应该得到多少积分
	    int addIntegeral = calculationSignIntegeral(continuityDate);
	    // 添加积分
	    synchronized (this) {
		this.integeralValue += addIntegeral;
	    }
	    // 计算等级
	    gradeCalculation();
	}

	public int calculationSignIntegeral(Integer continuityDate) {
	    return 1;
	}

	/**
	 * 等级计算
	 */
	private void gradeCalculation() {

	}
    }
}
相关文章
相关标签/搜索