锁优化的建议
来源:互联网 发布:冯大辉 范凯 知乎 编辑:程序博客网 时间:2024/06/05 10:32
1、减小锁持有时间
它的核心思想就是不要在不必需要的代码上加锁,因为线程持有的锁时间过长,相对地,锁的竞争程度也就越激烈。
看下面的代码:
public synchronized void syncMethod() { othercode1(); mutextMethod(); othercode2(); } public void syncMethod() { othercode1(); synchronized (this) { mutextMethod(); } othercode2(); }
2、减小锁锁粒度
减小锁粒度也是一种削弱多线程锁竞争的有效手段。典型的使用场景就是ConcurrentHashMap。
对于HashMap来说,最重要的两个方法就是get和put方法。一种最自然的想法就是对整个HashMap加锁,必然可以得到一个线程安全的对象。但是这样做,加锁的粒度太大,对于ConcurrentHashMap,它内部进一步细分了若干个小的HashMap,称之为段 segment。默认情况下ConcurrentHashMap,被进一步细分为16个段。
如果需要在ConcurentHashMap中增加一个新的表项,并不是将整个HashMap加锁,而是首先根据hashcode得到该表项应该被存放到那个段中,然后对该段加锁,并完成put操作。在多线程环境中,如果多个线程同时进行put操作,只要被加入的表项不存放在同一个段中,则线程间便可以做到真正的并行。
@SuppressWarnings("unchecked") public V put(K key, V value) { Segment<K,V> s; if (value == null) throw new NullPointerException(); int hash = hash(key); int j = (hash >>> segmentShift) & segmentMask; if ((s = (Segment<K,V>)UNSAFE.getObject // nonvolatile; recheck (segments, (j << SSHIFT) + SBASE)) == null) // in ensureSegment s = ensureSegment(j); return s.put(key, hash, value, false); }
3、 读写分离锁来替换独占锁
使用读写锁ReadWriteLock可以提供系统的性能。
4、 锁分离
如果将读写锁的思想做进一步的延伸,就是锁分离。典型的案例就是LinkedBlockingQueue的实现。
如果使用独占锁,则要求在两个操作进行时,获取当前队列的独占锁,那么take和put操作就不可能真正的并发,在运行时,它们会彼此等待对方释放锁资源。在这种情况下,锁竞争会相对比较激烈,从而影响程序在高并发的性能。
因此在JDK的实现中,并没有采用这样的方式,取而代之的是把两把不同的锁,分离了take和put操作。
/** Lock held by take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */ private final Condition notEmpty = takeLock.newCondition(); /** Lock held by put, offer, etc */ private final ReentrantLock putLock = new ReentrantLock(); /** Wait queue for waiting puts */ private final Condition notFull = putLock.newCondition();/** Current number of elements */ private final AtomicInteger count = new AtomicInteger(0);
下面来看下take的源码:
public E take() throws InterruptedException { E x; int c = -1; final AtomicInteger count = this.count; final ReentrantLock takeLock = this.takeLock; takeLock.lockInterruptibly();//只能有一个线程take元素。 try { while (count.get() == 0) {// 没有数据时,线程进入等待状态。 notEmpty.await(); } x = dequeue(); // 获取一个元素 c = count.getAndDecrement();//元素的数量减一 if (c > 1) notEmpty.signal();// 大于1,唤醒其他线程进行take操作。 } finally { takeLock.unlock(); } if (c == capacity) signalNotFull(); return x; }
下面看 put的源码
public void put(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); // Note: convention in all put/take/etc is to preset local var // holding count negative to indicate failure unless set. int c = -1; Node<E> node = new Node(e); final ReentrantLock putLock = this.putLock; final AtomicInteger count = this.count; putLock.lockInterruptibly(); try { /* * Note that count is used in wait guard even though it is * not protected by lock. This works because count can * only decrease at this point (all other puts are shut * out by lock), and we (or some other waiting put) are * signalled if it ever changes from capacity. Similarly * for all other uses of count in other wait guards. */ while (count.get() == capacity) {// 队列已经满了 notFull.await(); } enqueue(node); // 存放一个元素 c = count.getAndIncrement();//数量加一 if (c + 1 < capacity)// 还有空间,唤醒其他的线程进行put操作。 notFull.signal(); } finally { putLock.unlock(); } if (c == 0) signalNotEmpty(); }
、
5 、锁粗化
虚拟机在遇到一连串连续地对同一锁不断进行请求和释放的操作时,便会把所有的锁操作整合成对锁的一次请求,从而减少对锁的请求同步次数,这个操作叫做锁的粗化。
看下面的代码就清楚了
public void syncMethod() { synchronized (this) { mutextMethod2(); } synchronized (this) { mutextMethod2(); } }
public void syncMethod() { synchronized (this) { mutextMethod1(); mutextMethod2(); } }
- 锁优化的建议
- 搜索引擎优化的建议
- mysql优化的建议
- listview的优化建议
- 优化SQL的建议
- Lua的优化建议
- 优化PHP代码的建议
- SEO优化的成功建议
- [转]java的优化建议
- jQuery性能的优化建议
- 常见的SQL优化建议
- AS3的性能优化建议
- 最简单的优化建议:
- Unity的一些优化建议
- SEO优化的四个建议
- Android优化性能的建议
- android内存优化的建议
- 性能优化的十个建议
- Android支付宝支付开发流程
- 将Anaconda 的python2升级到python3
- 37 《这才是心理学》 -豆瓣评分9.0
- 【大话数据结构】字符串及模式匹配
- Android 获取File类视频文件的总时长
- 锁优化的建议
- bzoj2654 二分答案+最小生成树
- Android银联控件支付开发流程
- linux下mysql的卸载、安装全过程
- 微信小程序结构简介
- Git学习笔记
- Activity的onNewIntent方法执行时间
- 1. Two Sum 使用unsorted_map或者vector的sort函数
- python正则表达式初探