之前看了java8的longadder实现,最近又看到一篇文章介绍longadder的,http://ifeve.com/atomiclong-and-longadder/
其实现思路也是分段,最后需要get的时候进行sum计算。其核心思路就是减少并发,但之前老的Atomic,难道就没有提升的空间了吗?昨晚进行了一次测试
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
publicfinalint incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
以incrementAndGet为例,在非常高的并发下,compareAndSet会很大概率失败,因此导致了此处cpu不断的自旋,对cpu资源的浪费
既然知道此地是高并发的瓶颈,有什么办法呢?
publicclass AtomicBetter {
AtomicInteger ai = new AtomicInteger();
publicint incrementAndGet() {
for (;;) {
int current = ai.get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
/**
* 如果cas失败,线程park
* @param current
* @param next
* @return
*/
privateboolean compareAndSet(int current, int next) {
if (ai.compareAndSet(current, next)) {
returntrue;
} else {
LockSupport.parkNanos(1);
returnfalse;
}
}
}
很简单,当cas失败后,对线程park,减少多线程竞争导致的频繁cas失败,更进一步的导致cpu自旋,浪费cpu的运算能力
在4核虚拟机,Intel(R) Xeon(R) CPU E5-2630 0 @ 2.30GHz linux 2.6.32,注意,老版本的内核,不支持高ns级的精度
下进行测试,同样都起4个线程,每个线程里面对AtomicInteger进行5kw次的incrementAndGet
原生的AtomicInteger,耗时14232ms,进行了35870次上下文切换,总共87967770955次时钟周期
那prak 1ns下呢,耗时5195ms,进行了19779次上下文切换,总共36187480878次时钟周期
明显性能上比原生的AtomicInteger更好,那这个park多少合适呢?那就只有人肉测试了
park |
time (ms) |
context-switches |
cycles |
AtomicInteger |
14232 |
35,870 |
87,967,770,955 |
1ns |
5195 |
19,779 |
36,187,480,878 |
10ns |
5050 |
20,223 |
34,839,351,263 |
100ns |
5238 |
20,724 |
37,250,431,417 |
125ns |
4536 |
47,479 |
26,149,046,788 |
140ns |
4008 |
100,022 |
18,342,728,517 |
150ns |
3864 |
110,720 |
16,146,816,453 |
200ns |
3561 |
125,694 |
11,793,941,243 |
300ns |
3456 |
127,072 |
10,200,338,988 |
500ns |
3410 |
132,163 |
9,545,542,340 |
1us |
3376 |
134,463 |
9,125,973,290 |
5us |
3383 |
122,795 |
9,009,226,315 |
10us |
3367 |
113,930 |
8,905,263,507 |
100us |
3391 |
50,925 |
8,359,532,733 |
500us |
3456 |
17,225 |
8,096,303,146 |
1ms |
3486 |
10,982 |
7,993,812,198 |
10ms |
3456 |
2,600 |
7,845,610,195 |
100ms |
3555 |
1,020 |
7,804,575,756 |
500ms |
3854 |
822 |
7,814,209,077 |
本机环境下,park 1ms下,相对耗时,cs次数来说是最好的。因此这种优化要达到最佳效果,还要看cpu的情况而定,不是一概而定的
两个问题:
<!--[if !supportLists]-->1、<!--[endif]-->cas失败对线程park的副作用是什么
<!--[if !supportLists]-->2、<!--[endif]-->如果park的时间继续加大,那会是这么样的结果呢
相关推荐
值得注意的是,尽管`AtomicInteger`在单线程环境下可能较慢,但在多线程环境下,由于其线程安全特性,通常比非原子操作更快,因为它避免了同步带来的开销。然而,测试结果显示,`AtomicInteger`的性能比普通`int`慢...
3. 改善用户体验:多线程编程可以让程序更流畅、更快速地响应用户的交互操作,从而改善用户体验。 Thread 类 Thread 类是 Java 中的基本线程类,通过继承 Thread 类可以创建自己的线程类。Thread 类提供了几个重要...
公平锁保证按照线程等待的顺序获取锁,而非公平锁则可能更快地响应线程。 在选择锁时,开发者应考虑并发量、资源竞争程度、锁的粒度等因素。例如,如果共享资源的读操作远多于写操作,乐观锁可能是更好的选择。而在...
线程比进程更轻量级,创建和销毁更快,适合用于执行并行任务。 2. **线程的创建**:Java提供了多种创建线程的方式,如通过实现Runnable接口或继承Thread类。推荐使用Runnable接口,因为它可以避免单继承的限制。 3...
线程的轻量级特性使得线程间的切换相比进程更快,更适合于执行细粒度的任务。 线程上下文切换是线程调度的一部分,它是CPU时间片算法的结果。在一个CPU核心上,任何时刻只能执行一个线程。时间片分配机制允许CPU在...
5. **使用StringBuilder代替+操作符**:在字符串连接时,使用StringBuilder或StringBuffer的append方法比使用"+"更快,特别是在循环中。 6. **避免不必要的异常抛出与捕获**:异常处理有较高的开销,尽量在代码中...
这种方法通常比`synchronized`更快,但在某些情况下可能会导致内存可见性问题。 总之,理解和掌握Java中的线程、同步和并发是构建高效、可扩展的多线程应用程序的关键。合理地使用这些工具和机制,可以帮助我们编写...
总结来说,Java并发编程中的原子变量和非阻塞算法是应对锁的劣势的有效手段,它们提供了更高效、更灵活的并发控制机制,有助于开发出更稳定的并发应用程序。在设计高性能并发系统时,理解和熟练使用这些工具至关重要...
相比AVL树,红黑树允许更高的不平衡,但在插入和删除操作上更快。 9. **HTTPS和HTTP**:HTTPS是HTTP的安全版本,使用SSL/TLS协议加密通信,能保护数据的隐私和完整性,防止中间人攻击。其他安全传输手段包括SSH、...
例如,避免使用复杂度较高的排序算法,而选择更快速的排序方法如快速排序、归并排序等。 2. **数据结构优化**:合理使用数据结构,如数组、链表、哈希表等,能有效减少查找、插入和删除操作的时间复杂度。 3. **...
例如,可以设置生成者线程的优先级稍高于猜数线程,使得生成新数字的操作能更快完成。 6. **测试与调试**:在开发过程中,我们需要编写测试用例来验证线程安全性和游戏逻辑的正确性。可以使用Junit或其他测试框架...
可以自定义分词逻辑,也可以使用开源库如Apache Lucene或Stanford NLP进行更复杂的分词工作。 5. **统计词频**: - 遍历每个单词,如果在HashMap中存在,更新其值;如果不存在,则添加新键值对。 - 可以使用`...
【Java面试题大全】是针对专业Java开发人员的面试准备资料集合,涵盖了多个公司的常见面试题目,对于寻求Java职位的开发者来...在传智播客等专业机构的帮助下,可以更快地提升自己的技术水平,增加获得高薪工作的机会。
线程创建和销毁的开销小,切换更快。 2. **Java并发基础** - **Thread类**:Java中的线程是通过继承Thread类或实现Runnable接口来创建的。 - **守护线程(Daemon)**:用于后台服务,不阻塞程序退出。 - **线程...
5. **避免在循环中使用ArrayList的add()**:在大循环中,使用LinkedList会更快,因为它的插入时间复杂度是O(1)。 6. **缓存常用对象**:例如,使用`Integer.valueOf()`缓存-128到127的整数,以避免重复创建。 7. *...
1. **深度优先策略(DFS)**:考虑到多线程的实现和搜索深度的限制,选择深度优先策略作为链接遍历算法,以更高效地探索网络结构。 2. **正则表达式与HTML解析**:使用正则表达式快速匹配和提取URL链接,结合...
- **性能**:由于Hashtable的线程安全性是通过同步每个方法实现的,因此在非线程安全环境中使用HashMap通常更快。 通过以上分析可以看出,这些知识点都是在准备阿里巴巴面试时需要掌握的基本概念和技术细节。熟悉并...
8. **原子变量**:`java.util.concurrent.atomic`包中的原子变量类如`AtomicInteger`和`AtomicReference`,提供了无锁编程的支持,可以在不使用同步的情况下实现线程安全。 9. **并发设计模式**:书中涵盖了如生产...