您的位置:首页 > 其它

synchronized与lock,哪个效率更高

2014-08-29 17:11 120 查看
Java在一开始就提供了synchronized关键字,用于多线程之间的同步。它使用简便,不会出现拿锁之后不归还的情况,可以避免一些编程错误。

而jdk5时提供的concurrent包里,有一个Lock接口以及它的实现类:ReentrantLock。这个类提供了更灵活的控制以及更强大的功能。

如果单从性能方面考虑,两个哪个更高效呢?

首先是单线程的加锁情况,见以下代码:


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SynLockTest {

public static void main(String[] args) {
long value = 0;
int MAX = 10000000;
Lock lock = new ReentrantLock();
long start = System.nanoTime();
for (int i = 0; i < MAX; i++) {
synchronized (new Object()) {
value = value + 1;
}
}
long end = System.nanoTime();
System.out.println("synchronized cost: " + (end – start)/1000000 + "ms");

start = System.nanoTime();
for (int i = 0; i < MAX; i++) {
lock.lock();
try {
value = value + 1;
} finally {
lock.unlock();
}
}
end = System.nanoTime();
System.out.println("lock cost: " + (end – start) + "ns");
}
}


结果如下:


synchronized cost: 405ms
lock cost: 479ms


可见Lock的运行时间比synchronized略大。可以推测java编译器为synchronized做了特别优化。

再考虑多线程情况:


public class SynLockTest {

static class SynRunner implements Runnable {
private long v = 0;

@Override
public synchronized void run() {
v = v + 1;
}
}

static class LockRunner implements Runnable {
private ReentrantLock lock = new ReentrantLock();
private long v = 0;

@Override
public void run() {
lock.lock();
try {
v = v + 1;
} finally {
lock.unlock();
}
}

}

static class Tester {
private AtomicLong runCount = new AtomicLong(0);
private AtomicLong start = new AtomicLong();
private AtomicLong end = new AtomicLong();

public Tester(final Runnable runner, int threadCount) {
final ExecutorService pool = Executors.newFixedThreadPool(threadCount);
Runnable task = new Runnable() {
@Override
public void run() {
while (true) {
runner.run();
long count = runCount.incrementAndGet();
if (count == 1) {
start.set(System.nanoTime());
} else if (count >= 10000000) {
if (count == 10000000) {
end.set(System.nanoTime());
System.out.println(runner.getClass().getSimpleName() + ", cost: "
+ (end.longValue() – start.longValue())/1000000 + "ms"); }
pool.shutdown();
return;
}
}
}
};
for (int i = 0; i < threadCount; i++) {
pool.submit(task);
}
}
}

public static void main(String[] args) {
new Tester(new SynRunner(), 1);
new Tester(new LockRunner(), 1);
}

}


现在测试不同线程下的表现(时间单位ms):

1105010050010005000
synchronized542489446674700515151565178
lock838121182184785112111241
可以看到,在多线程环境并存在大量竞争的情况下,synchronized的用时迅速上升,而lock却依然保存不变或增加很少。

Lock是用CAS来实现的
JDK 1.6以上synchronized也改用CAS来实现了,所以两者性能差不多
Lock提供的功能丰富点,synchronized的使用简单点
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: