锁优化-减小锁粒度

锁优化-减小锁粒度锁优化有 3 个方向 1 减少持有锁的时间 例如 将 CPU 密集和 I O 密集的任务移到锁外 可以有效减少持有锁的时间 从而降低其他线程的阻塞时间

锁优化有3个方向:

1.减少持有锁的时间:例如,将CPU密集和I/O密集的任务移到锁外,可以有效减少持有锁的时间,从而降低其他线程的阻塞时间。

2.减小加锁的粒度:将单个独占锁变为多个锁,从而将加锁请求均分到多个锁上,有效降低对锁的竞争。但是,增加锁的前提是多线程访问的变量间相互独立,如果多线程需要同时访问多个变量,则很难进行锁分解,因为要维持原子性。

3.放弃使用独占锁,使用非阻塞算法来保证并发安全。例如,使用并发容器、读写锁、不可变对象、原子变量、线程封闭等技术。

本文介绍减小锁粒度的方法:

public class ServerStatus { public final Set<String> users; public final Set<String> queries; public ServerStatus() { users = new HashSet<>(); queries = new HashSet<>(); } / * 独占锁意味着增加资源不能提升程序吞吐量,可伸缩性很差 * @param user */ public synchronized void addUser(String user) { users.add(user); } public synchronized void addQuery(String q) { queries.add(q); } public synchronized void removeUser(String user) { users.remove(user); } public synchronized void removeQuery(String query) { users.remove(query); } }
/ * 锁分解技术是减小了锁粒度,将锁住所有变量的全局锁变为锁住部分变量的局部锁。 * 锁分解能提升吞吐量的原理是将对一个锁的竞争均摊到2个锁上,从而降低了对单个锁的请求频率,有效地降低了竞争程度。 * 不足:与独占锁相比,锁分解技术在多处理器系统中只能将吞吐量提高一倍,可伸缩性还是受到限制。 */ public class ServerStatusLockDecompose { public final Set<String> users; public final Set<String> queries; public ServerStatusLockDecompose() { users = new HashSet<>(); queries = new HashSet<>(); } / * 独占锁意味着增加资源不能提升程序吞吐量,可伸缩性很差 * @param user */ public void addUser(String user) { synchronized(users) { users.add(user); } } public void addQuery(String q) { synchronized(queries) { queries.add(q); } } public void removeUser(String user) { synchronized(users) { users.remove(user); } } public void removeQuery(String query) { synchronized(queries) { queries.remove(query); } } }

当处理器增加时,分解锁的性能不能持续提升,所以,可以使用分段锁,要求是数据独立同分布,每个锁保护一部分数据。

/ * buckets[n]由locks[n % N_LOCKS]来保护 */ public class StrippedMap { private static final int N_LOCKS = 16; private final Node[] buckets; private final Object[] locks; private static class Node{ Object key; Object value; Node next; Node(Object key, Object value) { this.value = value; this.key = key; } void setNext(Node next) { this.next = next; } } public StrippedMap(int numBuckets) { buckets = new Node[numBuckets]; locks = new Object[N_LOCKS]; for(int i = 0; i < N_LOCKS; i++) { locks[i] = new Object(); } } private final int hash(Object key) { return Math.abs(key.hashCode() % buckets.length); } public Object get(Object key) { int hash = hash(key); synchronized (locks[hash % N_LOCKS]) { for(Node m = buckets[hash]; m != null; m = m.next) { if(m.key.equals(key)) { return m.value; } } } return null; } public void put(Object key, Object value) { int hash = hash(key); synchronized (locks[hash % N_LOCKS]) { Node node = buckets[hash]; Node preNode = node; while (node != null) { preNode = node; node = node.next; } Node currentNode = new Node(key,value); currentNode.setNext(null); if(preNode == null) { buckets[hash] = currentNode; return; } preNode.setNext(currentNode); return; } } public void clear() { for(int i = 0; i < buckets.length; i++) { synchronized (locks[i % N_LOCKS]) { buckets[i] = null; } } } public static void main(String[] args) { StrippedMap map = new StrippedMap(16); map.put("test", 123); map.put("test1", 1); map.put("abs", 1); System.out.println(map.get("abs")); System.out.println(map.get("test")); System.out.println(map.get("test1")); } }

对锁的优化,是建立在保证程序正确性的基础上的,所以,先保证程序能正常运行,当吞吐量达不到期望时,才能考虑性能优化,过早的优化就是灾难。

参考《Java并发编程实战》

今天的文章 锁优化-减小锁粒度分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2025-01-03 12:57
下一篇 2025-01-03 12:51

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/100600.html