面试题答案
一键面试性能问题
- 竞争激烈:Hashtable的方法大多是synchronized修饰的,在高并发下,所有线程访问Hashtable的方法都会竞争同一把锁,导致大量线程阻塞等待,降低了并发性能。
- 锁粒度大:整个Hashtable实例只使用一把锁,使得即使不同线程访问不同的键值对,也会因为锁的竞争而影响性能。
- 死循环风险:在扩容操作时,如果多个线程同时进行操作,可能会导致链表形成循环,进而在获取元素时陷入死循环。
优化方法
- 使用ConcurrentHashMap:
- 锁分段机制:ConcurrentHashMap采用锁分段技术,它将数据分成多个段(Segment),每个段都有自己的锁。不同线程访问不同段的数据时,不会产生锁竞争,从而提高并发性能。
- 读操作无锁:ConcurrentHashMap的读操作大多是无锁的,通过volatile关键字保证数据的可见性,进一步提高读性能。在高并发读多写少的场景下,性能优势明显。
- 减小锁粒度:
- 自定义锁机制:如果不能替换Hashtable,可以通过自定义锁机制来减小锁粒度。例如,将数据按照一定规则进行分区,每个分区使用单独的锁,使得不同线程可以并发访问不同分区的数据。
- 读写分离:
- 使用读写锁:引入ReadWriteLock,读操作使用读锁,允许多个线程同时进行读操作;写操作使用写锁,在写操作时,其他读写操作都被阻塞。这种方式适合读多写少的场景,可以提高整体性能。
- 合理设置初始容量:
- 避免频繁扩容:在创建Hashtable(或类似替代集合)时,根据预估的数据量合理设置初始容量,避免在高并发环境下频繁扩容。扩容操作会涉及到数据的重新计算和迁移,消耗大量资源,影响性能。