锁的优化

1 减少锁持有时间
对于使用锁进行并发控制的应用程序来说,如果单个线程特有锁 的时间过长,会导致锁的竞争更加激烈,会影响系统的性能.在程序中 需要尽可能减少线程对锁的持有时间,如下面代码:
public synchronized void syncMethod(){
othercode1();
mutexMethod();
othercode2(); }
在syncMethod同步方法中,假设只有mutexMethod()方法是需要同 步的, othercode1()方法与 othercode2()方法不需要进行同步. 如果othercode1 与 othercode2 这两个方法需要花费较长的 CPU 时间,在并 发量较大的情况下,这种同步方案会导致等待线程的大量增加. 一个 较好的优化方案是,只在必要时进行同步,可以减少锁的持有时间,提 高系统的吞吐量,如把上面的代码改为:
public void syncMethod(){
othercode1();
synchronized (this) {
mutexMethod(); }
othercode(); }
只对 mutexMethod()方法进行同步,这种减少锁持有时间有助于降 低锁冲突的可能性,提升系统的并发能力.

2 减小锁的粒度
一个锁保护的共享数据的数量大小称为锁的粒度. 如果一个锁保 护的共享数据的数量大就称该锁的粒度粗,否则称该锁的粒度细.锁的 粒度过粗会导致线程在申请锁时需要进行不必要的等待.减少锁粒度 是一种削弱多线程锁竞争的一种手段,可以提高系统的并发性

3 使用读写分离锁代替独占锁

使用ReadWriteLock读写分离锁可以提高系统性能, 使用读写分离 锁也是减小锁粒度的一种特殊情况. 第二条建议是能分割数据结构 实现减小锁的粒度,那么读写锁是对系统功能点的分割.
在多数情况下都允许多个线程同时读,在写的使用采用独占锁,在 读多写少的情况下,使用读写锁可以大大提高系统的并发能力.

4 锁分离
将读写锁的思想进一步延伸就是锁分离.读写锁是根据读写操作 功能上的不同进行了锁分离.根据应用程序功能的特点,也可以对独占 锁进行分离.如 java.util.concurrent.LinkedBlockingQueue 类中 take()与 put()方法分别从队头取数据,把数据添加到队尾. 虽然这两个方法都 是对队列进行修改操作,由于操作的主体是链表,take()操作的是链表 的头部,put()操作的是链表的尾部,两者并不冲突. 如果采用独占锁的 话,这两个操作不能同时并发,在该类中就采用锁分离,take()取数据时 有取锁, put()添加数据时有自己的添加锁,这样 take()与 put()相互独立 实现了并发

5 粗锁化
为了保证多线程间的有效并发,会要求每个线程持有锁的时间尽 量短.但是凡事都有一个度,如果对同一个锁不断的进行请求,同步和 释放,也会消耗系统资源.如:
public void method1(){
synchronized( lock ){
同步代码块 1 }
synchronized( lock ){
同步代码块 2 } }
JVM 在遇到一连串不断对同一个锁进行请求和释放操作时,会把所 有的锁整合成对锁的一次请求,从而减少对锁的请求次数,这个操作叫 锁的粗化,如上一段代码会整合为:
public void method1(){ synchronized( lock ){
同步代码块 1 同步代码块 2 }
}

posted @ 2021-08-30 15:37  x77  阅读(78)  评论(0)    收藏  举报