來自:https://www.cnblogs.com/willowWind/p/8551926.html
今天使用synchronized和java unsafe cas接口對比了下同一個操作下的的相關性能,
爲後面多線程情況下使用synchronized同步阻塞方式或者是unsafe cas非阻塞做了一個參考。
測試用例:
啓用多個線程進行計數相加到一億,首先是synchronized方式;
計算類如下:
package com.wc.thread;
public class SyncCounter implements CountBase{
private volatile long value = 0;
@Override
public synchronized long getValue() {
// TODO Auto-generated method stub
return value;
}
@Override
public synchronized long increment() {
// TODO Auto-generated method stub
if (value <= 100000000)
return ++value;
else
return value;
}
}
測試類:
package com.wc.thread;
public class Test {
public static void main(String[] args) {
CountBase counter= new SyncCounter();
for(int i =0; i< 64; i++)
{
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
long begin = System.currentTimeMillis();
while(true)
{
if(counter.getValue() >= 100000000)
break;
else
{
counter.increment();
}
}
long end = System.currentTimeMillis();
long time = end - begin;
System.out.println("The process is " + Thread.currentThread().getName() +
" Value is :" + counter.getValue() + ";" + "time is:" + time);
}
}
);
thread.start();
}
}
}
測試相關數據如下:
當線程數爲8時,性能明顯提升,但是8到32個線程來說,每個線程的平均時間基本差不多,基本沒有提升,到了64個線程的時候,性能又有一點提升。
如果換成CAS實現多線程累加數爲一億,時間又會怎麼樣呢,我們先來看下測試代碼:
計算類如下:
package com.wc.thread;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class CasCounter implements CountBase{
private volatile long value = 0;
private static Unsafe un;
private static long valueOffset;
static
{
try{
un = getUnsafeInstance();
valueOffset = un.objectFieldOffset(CasCounter.class.getDeclaredField("value"));
}catch (Exception e) {
// TODO: handle exception
System.out.println("init unsafe error!");
}
}
@Override
public long getValue() {
// TODO Auto-generated method stub
return value;
}
@Override
public long increment() {
// TODO Auto-generated method stub
long current;
long next;
for(;;)
{
current = value;
next = current + 1;
if(value >= 100000000)
return value;
if(un.compareAndSwapLong(this, valueOffset, current, next))
return next;
}
}
private static Unsafe getUnsafeInstance() throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
}
測試類和之前類似,只需要用CasCounter類實例化CountBase接口即可;
統計數據如下:
對比兩個結果我們可知:
在線程數相對較少的時候,CAS實現比較快,性能優於synchronized,當線程數多於8後,CAS實現明顯開始下降,反而時間消耗高於synchronized;
以上結果表明,synchronized是java提供的又簡單方便,性能優化又非常好的功能,建議大家常用;CAS的話,線程數大於一定數量的話,多個線程在
循環調用CAS接口,雖然不會讓其他線程阻塞,但是這個時候競爭激烈,會導致CPU到達100%,同時比較耗時間,所以性能就不如synchronized了。