Java中AtomicInteger与synchronized int变量:性能差异
经过下面的问题 ,Java中AtomicInteger与synchronized int变量:性能差异,java,atomic,synchronized,java.util.concurrent,Java,Atomic,Synchronized,Java.util.concurrent,经过下面的问题 , 我编写了一个简单的程序来比较AtomicInteger和synchronized块(在其中递增int)的性能差异。每次我运行这个程序,它给我的比率>100。 我的笔记本电脑有Intel Corei3和以下第4行 System.out.println(Runtime.getRuntime().availableProcessors()) 当我使用 THREAD_COUNT = 1; 这个比率是最低的。它在100左右变化。为了 THREAD_COUNT
我编写了一个简单的程序来比较AtomicInteger和synchronized块(在其中递增int)的性能差异。每次我运行这个程序,它给我的比率>100。 我的笔记本电脑有Intel Corei3和以下第4行
System.out.println(Runtime.getRuntime().availableProcessors())
当我使用
THREAD_COUNT = 1;
这个比率是最低的。它在100左右变化。为了
THREAD_COUNT = 10;
比率约为800
问题1:您能告诉我这是测试AtomicInteger与synchronized increment()方法性能差异的正确方法吗
问题2:如果我增加线程数
,比率会增加,为什么?我认为这是因为更多的线程在synchronized语句中被阻塞,需要更多的CPU任务。请评论
package concurrent.atomic;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Performance {
private static final AtomicInteger atomicInt = new AtomicInteger(0);
private static volatile int counter = 0;
private static final Object LOCK = new Object();
private static final int THREAD_COUNT = 10;
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().availableProcessors());
Runnable atomic = new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
int value = atomicInt.incrementAndGet();
//if (value % 1000 == 0)
//System.out.println("atomic value : "+value);
}
}
};
//System.out.println("1");
Runnable intCounter = new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
synchronized (LOCK) {
int value = ++counter;
//if (value % 1000 == 0)
//System.out.println("sync value "+value);
}
}
}
};
final ExecutorService atomicExecutor = Executors.newCachedThreadPool();
final ExecutorService primitiveExecutor = Executors.newCachedThreadPool();
for (int i = 0; i < THREAD_COUNT ; ++i) {
atomicExecutor.submit(atomic);
primitiveExecutor.submit(intCounter);
}
while (true) {
float ratio = (((float) (atomicInt.get() * 1.0) ) / counter) * 100;
System.out.println("ratio : " + ratio);
}
}
}
package concurrent.atomic;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.AtomicInteger;
公开课表演{
私有静态最终AtomicInteger atomicInt=新的AtomicInteger(0);
专用静态易失性int计数器=0;
私有静态最终对象锁=新对象();
私有静态最终整数线程计数=10;
公共静态void main(字符串[]args){
System.out.println(Runtime.getRuntime().availableProcessors());
Runnable-atomic=新的Runnable(){
@凌驾
公开募捐{
而(!Thread.currentThread().isInterrupted()){
int value=atomicInt.incrementAndGet();
//如果(值%1000==0)
//System.out.println(“原子值:“+value”);
}
}
};
//系统输出打印项次(“1”);
Runnable intCounter=new Runnable(){
@凌驾
公开募捐{
而(!Thread.currentThread().isInterrupted()){
已同步(锁定){
int值=++计数器;
//如果(值%1000==0)
//System.out.println(“同步值”+值);
}
}
}
};
final ExecutorService atomicExecutor=Executors.newCachedThreadPool();
final ExecutorService primitiveExecutor=Executors.newCachedThreadPool();
对于(int i=0;i
问题1:你能告诉我这是测试AtomicInteger与synchronized increment()方法性能差异的正确方法吗
测试代码存在一些微妙的问题:
- 如果在
,则锁上进行同步
不应为计数器
。否则,易失性
代码将支付锁和synchronized
的费用volatile
- 如果
不是计数器
,则在读取易失性
的值时,需要在计数器
上进行同步锁定
- 你不应该在主线程中旋转。这将极大地影响您的性能测试。放一个
线程。睡眠(100)至少在
循环时,在
中执行code>
- 原来
在我的Mac上非常昂贵。不知道为什么。当(true)更改数字时,将其切换为Thread.currentThread().isInterrupted()
package concurrent.atomic;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Performance {
private static final AtomicInteger atomicInt = new AtomicInteger(0);
private static volatile int counter = 0;
private static final Object LOCK = new Object();
private static final int THREAD_COUNT = 10;
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().availableProcessors());
Runnable atomic = new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
int value = atomicInt.incrementAndGet();
//if (value % 1000 == 0)
//System.out.println("atomic value : "+value);
}
}
};
//System.out.println("1");
Runnable intCounter = new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
synchronized (LOCK) {
int value = ++counter;
//if (value % 1000 == 0)
//System.out.println("sync value "+value);
}
}
}
};
final ExecutorService atomicExecutor = Executors.newCachedThreadPool();
final ExecutorService primitiveExecutor = Executors.newCachedThreadPool();
for (int i = 0; i < THREAD_COUNT ; ++i) {
atomicExecutor.submit(atomic);
primitiveExecutor.submit(intCounter);
}
while (true) {
float ratio = (((float) (atomicInt.get() * 1.0) ) / counter) * 100;
System.out.println("ratio : " + ratio);
}
}
}
AtomicInteger.incrementAndGet()
通过旋转工作,直到测试和设置成功。这与锁获取、增量和释放非常不同。在不知道操作系统线程处理细节的情况下,很难解释这里发生了什么,我不确定这在所有情况下都是正确的
在我的测试中,随着线程的数量越来越多地超过处理器的数量,这个比率往往会有相当大的波动。随着更多线程的添加,
synchronize
处理明显受到并发性增加的影响,尽管我不确定还能从中得出什么结论。做到了这一点。我在谷歌上找到了这个。试试这个。你这里有一个bug,你需要将计数器
声明为volatile
。否则,不能保证主线程读取最新的值。是。。我需要更改我的代码。你的分析有道理。您可以不时将计数器重置为0,以避免溢出,更重要的是在JIT前后进行计算。