ReentrantLock是jdk5引入的新的锁机制,它与内部锁(synchronize) 相同的并发性和内存语义,比如可重入加锁语义。在中等或者更高负荷下,ReentrantLock有更好的性能,并且拥有可轮询和可定时的请求锁等高级功能。这个程序简单对比了ReentrantLock公平锁、ReentrantLock非公平锁以及内部锁的性能,从结果上看,非公平的ReentrantLock表现最好。内部锁也仅仅是实现统计意义上的公平,结果也比公平的ReentrantLock好上很多。这个程序仅仅是计数,启动N个线程,对同一个Counter进行递增,显然,这个递增操作需要同步以保证原子性,采用不同的锁来实现同步,然后查看结果。
Counter接口:
package net.rubyeye.concurrency.chapter13;
public interface Counter {
public long getValue();
public void increment();
}
然后,首先使用我们熟悉的synchronize来实现同步:
package net.rubyeye.concurrency.chapter13;
public class SynchronizeBenchmark implements Counter {
private long count = 0;
public long getValue() {
return count;
}
public synchronized void increment() {
count++;
}
}
采用ReentrantLock的版本,切记要在finally中释放锁,这是与synchronize使用方式最大的不同,内部锁jvm会自动帮你释放锁,而ReentrantLock需要你自己来处理。
package net.rubyeye.concurrency.chapter13;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockBeanchmark implements Counter {
private volatile long count = 0;
private Lock lock;
public ReentrantLockBeanchmark() {
// 使用非公平锁,true就是公平锁
lock = new ReentrantLock(false);
}
public long getValue() {
// TODO Auto-generated method stub
return count;
}
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
写一个测试程序,使用CyclicBarrier来等待所有任务线程创建完毕以及所有任务线程计算完成,清单如下:
package net.rubyeye.concurrency.chapter13;
import java.util.concurrent.CyclicBarrier;
public class BenchmarkTest {
private Counter counter;
private CyclicBarrier barrier;
private int threadNum;
public BenchmarkTest(Counter counter, int threadNum) {
this.counter = counter;
barrier = new CyclicBarrier(threadNum + 1); //关卡计数=线程数+1
this.threadNum = threadNum;
}
public static void main(String args[]) {
new BenchmarkTest(new SynchronizeBenchmark(), 5000).test();
//new BenchmarkTest(new ReentrantLockBeanchmark(), 5000).test();
//new BenchmarkTest(new ReentrantLockBeanchmark(), 5000).test();
}
public void test() {
try {
for (int i = 0; i < threadNum; i++) {
new TestThread(counter).start();
}
long start = System.currentTimeMillis();
barrier.await(); // 等待所有任务线程创建
barrier.await(); // 等待所有任务计算完成
long end = System.currentTimeMillis();
System.out.println("count value:" + counter.getValue());
System.out.println("花费时间:" + (end - start) + "毫秒");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
class TestThread extends Thread {
private Counter counter;
public TestThread(final Counter counter) {
this.counter = counter;
}
public void run() {
try {
barrier.await();
for (int i = 0; i < 100; i++)
counter.increment();
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
分别测试一下,
将启动的线程数限定为500,结果为:
公平ReentrantLock: 210 毫秒
非公平ReentrantLock : 39 毫秒
内部锁: 39 毫秒
将启动的线程数限定为1000,结果为:
公平ReentrantLock: 640 毫秒
非公平ReentrantLock : 81 毫秒
内部锁: 60 毫秒
线程数不变,test方法中的循环增加到1000次,结果为:
公平ReentrantLock: 16715 毫秒
非公平ReentrantLock : 168 毫秒
内部锁: 639 毫秒
将启动的线程数增加到2000,结果为:
公平ReentrantLock: 1100 毫秒
非公平ReentrantLock: 125 毫秒
内部锁: 130 毫秒
将启动的线程数增加到3000,结果为:
公平ReentrantLock: 2461 毫秒
非公平ReentrantLock: 254 毫秒
内部锁: 307 毫秒
启动5000个线程,结果如下:
公平ReentrantLock: 6154 毫秒
非公平ReentrantLock: 623 毫秒
内部锁: 720 毫秒
非公平ReentrantLock和内部锁的差距,在jdk6上应该缩小了,据说jdk6的内部锁机制进行了调整
分享到:
相关推荐
ReentrantLock的内部类Sync继承自AQS,进一步分为FairSync(公平锁)和NonfairSync(非公平锁)两个子类。公平锁确保线程按照它们请求锁的顺序获取锁,而非公平锁则不保证这种顺序,可能会有线程插队获取锁。 **...
- **性能对比**:比较`ReentrantLock`与`synchronized`关键字在特定场景下的性能差异。 ### 结论 AQS和`ReentrantLock`是Java并发编程中重要的组成部分,通过对它们的理解和掌握,可以更好地设计和实现高性能的...
5. **公平性和非公平性**:ReentrantLock提供了公平锁和非公平锁的选择。公平锁确保按照请求顺序分配锁,非公平锁则不保证,通常非公平锁的性能更高,因为它减少了线程调度的开销。 **读写锁(ReadWriteLock)和...
这篇文章将深入探讨这两个类的性能对比及其背后的原理。 `HashMap`是Java集合框架中的基础类,首次出现在JDK 1.2版本中,主要用于非线程安全的场景。它的核心实现基于开放寻址法和链表,通过数组和链表的结合来存储...
2. **可重入锁(ReentrantLock)**:是Java `java.util.concurrent.locks`包提供的锁,它具有与内置锁相似的功能,但提供了更高级的特性,如公平锁、非公平锁、尝试锁、定时锁和条件变量等。 3. **读写锁...
Java中的`synchronized`关键字和`ReentrantLock`类是悲观锁的代表。 3. **自旋锁与适应性自旋锁**: - **自旋锁**:当一个线程尝试获取已被其他线程持有的锁时,它不会立即阻塞,而是循环地检查锁是否可用,这就是...
67. Synchronized与ReentrantLock对比,Synchronized是内置锁,使用简单,ReentrantLock提供了更细粒度的控制,如公平锁、可中断锁、tryLock等。 68. ReentrantLock的可重入性源于持有锁的线程再次请求锁时不会阻塞...
线程是操作系统调度的基本单位,它是进程...基于AQS的类如`ReentrantLock`、`Semaphore`等,都利用AQS的抽象方法和内部状态来实现各自的同步逻辑。AQS解决了锁和同步器的许多底层实现细节,简化了开发同步组件的工作。
ReentrantLock的内部结构包含一个Sync对象,Sync是AQS的子类,进一步分为FairSync(公平锁)和NonFairSync(非公平锁)两个子类。 6. **获取公平锁的过程** 当线程调用ReentrantLock的`lock()`方法时,实际是调用...
10. **使用适当的同步机制**:避免使用synchronized关键字的全局锁,可以考虑使用ReentrantLock、ConcurrentHashMap等并发容器,以减少锁竞争。 11. **使用流式API (Stream API)**:Java 8引入的流API可以简化处理...
3. Lock接口:理解ReentrantLock、Condition等高级锁的用法。 4. 线程池:了解ExecutorService、ThreadPoolExecutor和ScheduledExecutorService的使用。 五、IO与NIO篇 1. 文件操作:掌握File类的使用,进行文件的...
ReentrantLock是可重入的互斥锁,支持公平和非公平策略。 4. **并发集合**:`03-并发List、Set、ConcurrentHashMap底层原理剖析-monkey`涵盖了Java并发集合的讨论。ConcurrentHashMap是一种线程安全的哈希映射表,...
- Lock接口与ReentrantLock:理解锁的高级特性,如公平锁、非公平锁、可重入锁。 8. **IO与NIO** - 流的概念:理解字节流和字符流的区别,以及InputStream、OutputStream、Reader、Writer家族。 - 文件操作:...
`Unsafe`是一个内部类,提供了直接内存访问和一些底层操作,如CAS。`AtomicInteger`的`incrementAndGet()`方法就是一个典型的例子,它通过`unsafe.getAndAddInt()`实现自增,这个过程就是基于CAS操作的。 3. **ABA...
5. Synchronized 和 Volatile 关键字的比较:volatile 关键字是另一个用于控制内存可见性的关键字,它保证了变量的可见性,即对一个volatile变量的读总是能获取到最新的写入值。尽管volatile提供了某些同步的特性,...
每个Segment继承自`ReentrantLock`,因此可以独立加锁和解锁。 JDK1.7的`ConcurrentHashMap`结构: 1. **Segment**:类似于HashMap,由Entry数组和链表组成。每个Segment包含一个锁,用于控制对相应数据段的访问。 ...
3. ReentrantLock与synchronized的对比,以及如何选择合适的锁策略。 4. 并发容器的线程安全实现及性能优化技巧。 5. 原子变量的无锁编程实践和效率分析。 6. 同步工具类在多线程协调中的应用案例。 7. Future和...