Java 提高锁性能的5点建议

2021-01-22  本文已影响0人  贼噶人

减少锁持有的时间

对于使用锁来进行并发控制的程序而言,线程对锁的持有时间越长,必能会导致锁竞争变的越激烈。
可以想象下我们排队买包子,买包子的窗口只有那么几个,如果轮到我们了我们才去想要买什么包子,势必会影响整个队伍的效率,所以我们应该在之前就想好自己要买什么包子。

public synchronized void syncFunc(){
      func1();
      mutexFunc();
      func2();
}

如果以上代码的func1和func2都是比较耗时的方法,但是他不需要同步,只有中间的方法需要同步,如果我们这么写势必会造成整个方法持有锁的时间,时间长了会导致竞争概率的提高,白白浪费系统资源,影响程序性能,所以只对有需要的方法加lock。

public void syncFunc(){
      func1();
      synchronized(lock) {
          mutexFunc();
      }  
      func2();
}

较少锁的粒度

ConcurrentHashMap就是一个很好的例子,比如其put方法发生Hash冲突时他只是对该Node进行加锁操作。

读写分离

读操作不会影响数据的属性和结构,所以我们对于读-读线程间就不需要同步,来减少锁的竞争。

锁分离

LinkedBlockingQueue 就是一个很好的例子,我们知道其是链表实现的,主要的操作有take和put,并且其分别在head和tail进行操作,之间是没有影响的,所以其使用两把锁分别来控制其take和put操作。

 public E take() throws InterruptedException {
        E x;
        int c = -1;
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();
        try {
            while (count.get() == 0) {
                notEmpty.await();
            }
            x = dequeue();
            c = count.getAndDecrement();
            if (c > 1)
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }
public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        int c = -1;
        Node<E> node = new Node<E>(e);
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
        putLock.lockInterruptibly();
        try 
            while (count.get() == capacity) {
                notFull.await();
            }
            enqueue(node);
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
    }

粗化锁

for () {
  synchronized(lock) { // 本身锁的申请和释放都是有代价的,所以我们要进行粗化
      //code    
  }
}
synchronized(lock) {
for () {
   // 本身锁的申请和释放都是有代价的,所以我们要进行粗化
      //code 
    }
  }
上一篇 下一篇

猜你喜欢

热点阅读