Java锁原理漫谈

从网上看了很多关于Java的锁的解释,感觉大多数讲解的都是锁的实现(可能深入到JVM让大家比较有成就感),但是对于锁的应用以及应用该注意的内容都略少,这里把我的一些经验跟大家分享一下:

PS:本处讲解的锁都是针对Java中的synchronized关键字。

 

首先锁是怎么来的,

这个要追溯到synchronized关键字,这个关键字可以应用在方法上也可以写在某个代码块,应用于方法上的时候,根据方法本来的所属域,自动增加相应的锁,比如static方法获取的锁就是class类,而普通的方法的锁则是当前实例也就是this,怎么说呢,下面的代码是等价的:

Public synchronized void mutlRun(){

//do something

};

等价于

Public void mutlRun(){

       Synchronized(this){

//do something

}

};

 

同理static method

Public static synchronized void mutlRun(){

//do something

};

等价于

Public static void mutlRun(){

       Synchronized(***.class){

//do something

}

};

可以看到方法的内部有一个代码块,该代码块的起始部分可以写入某个变量或者什么东西,然后多线程的时候多个线程会使用指定的对象作为锁,谁首先获得该对象的访问权,谁就可以执行接下来的代码,其余的wait

 

有了上面的基础,那我们来看看业务该怎么思考这个锁:

  1. 锁的应用场景

  2. a)         很多地方说锁是用在多线程里面,其实少了半句,锁是在多线程里面针对某一个共享资源进行调配的一种方案。如果不存在共享资源,就不需要锁,那么问题来了,什么叫做共享资源,简单的罗列几个:

i.              静态变量 – static Object这种

ii.              单例中的实例属性,Singleton.getProperty这种

iii.              系统全局可以引用到的部分,比如:web编程中的Session或者application中的数据

iv.              本地文件

v.              数据库数据等。。所有的JVM之外的同步化数据

  1. 锁的粒度控制

  2. a)         通过上面的介绍可以看到锁其实是将多线程约束起来的一种方式,那么势必多线程会被约束成单线程,最起码相同的锁无法并行,那么怎么保证性能就成为一个很重要的话题

  3. b)         通过上面的代码可以看到当锁为.class的时候,全JVM因为只有一个.class对象的实例,所以所有的线程运行到代码区都会变成顺序的。从而多线程,变成了单线程。如果说这块代码会被很多地方用到,显然不合适,这时候就需要根据情况使用定制化的锁

  4. c)         简单介绍一个锁的生成方案,使用某个方法来生成锁,并且缓存,比如将业务的ID放到MAP里面去,类似于map.put(“id_001”,new Object());这样当001的业务线程进来的时候获取的都是同一个object,因而会产生同步,而002进来的时候获取的是另一个object,所以不会跟001的线程产生同步,从而加快运行速度。(注意,业务补习没有纠缠)

 

锁这个东西其实又简单又复杂,用的好了,能使系统获得很高的并发,但是记住,任何一个synchronized的地方都有一个锁的存在,时时刻刻要关注锁到底会影响到谁。


你可能感兴趣的:(Java锁原理漫谈)