Intellij IDEA多线程调试——ConcurrentHashMap并发扩容

调试代码

1.构造两个线程

多线程并发扩容,每个线程都负责一段tab进行处理,最小的一段是16。因此16->32扩容时,只有一个线程进行扩展。
为了能获得两个线程并发调试的效果,需要直接将默认容量定位32。

public class CHMTest extends Thread {

    static ConcurrentHashMap map = new ConcurrentHashMap<>(32);
    static AtomicInteger at = new AtomicInteger(1);

    public void run()
    {
        if (Thread.currentThread().getName().equals("thread0")) {
            System.out.println("thread 0");
            for (int i = 1; i < 1000000; ++i){
                map.put(28 + (i << 5), 28 + (i << 5));
                map.put(21 + (i << 5), 21 + (i << 5));
            }
        } else if (Thread.currentThread().getName().equals("thread1")){
            System.out.println("thread 1");
            for (int i = 1; i < 1000000; ++i){
                map.put(29 + (i << 5), 29 + (i << 5));
                map.put(22 + (i << 5), 22 + (i << 5));
            }
        }
    }

    public static void main(String[] args) {
        CHMTest t0 = new CHMTest();
        t0.setName("thread0");
        CHMTest t1 = new CHMTest();
        t1.setName("thread1");
//        CHMTest t2 = new CHMTest();
//        CHMTest t3 = new CHMTest();
        t0.start();
        t1.start();
//        t2.start();
//        t3.start();
    }
}

2.多线程调试方法

对于多线程调试来说,最重要的就是控制两个线程的执行顺序,我们要做的其实就是当另一个不处于调试状态的线程命中断点后,能先暂停,一直等到我去处理为止。
在断点处右键:


Intellij IDEA多线程调试——ConcurrentHashMap并发扩容_第1张图片

它提供了两种挂起的模式,默认的是All,只需要选中Thread,它就会一直等待到你处理它。
在这里切换线程:


Intellij IDEA多线程调试——ConcurrentHashMap并发扩容_第2张图片

3.多线程调试

  • step1.先打两个断点,F9运行一次


    Intellij IDEA多线程调试——ConcurrentHashMap并发扩容_第3张图片
  • step2.再打addCount里面的transfer断点,运行直到扩容,此时tab大小为64,扩容是在48发生


    Intellij IDEA多线程调试——ConcurrentHashMap并发扩容_第4张图片
Intellij IDEA多线程调试——ConcurrentHashMap并发扩容_第5张图片
  • step3.transfer()里面打断点,在helpTransfer里面的transfer处打断点;在线程thread1里面(此时使用F7/F8,F9会进行线程切换,没法控制)运行直到49变为的ForwardingNode


    Intellij IDEA多线程调试——ConcurrentHashMap并发扩容_第6张图片
  • step4.在线程thread0里面F7/F8运行,因为28+32=60,此时60变为了ForwardingNode,所以会进入helpTransfer进行扩容,此时的transferIndex = 48,表明thread0扩容是从47开始向下的一个16大小的段(也即32-47)


    Intellij IDEA多线程调试——ConcurrentHashMap并发扩容_第7张图片

    运行几次,会发现47 46变为ForwardingNode


    Intellij IDEA多线程调试——ConcurrentHashMap并发扩容_第8张图片
  • step5.此时再切换到thread1,使用F7/F8运行完48-63这段的扩容操作。继续向下的时候,会发现transferIndex=32,所以thread1接着处理16-31这一段,同时transferIndex变为16


    Intellij IDEA多线程调试——ConcurrentHashMap并发扩容_第9张图片

参考

  • 1)Idea Intellij多线程调试

你可能感兴趣的:(Intellij IDEA多线程调试——ConcurrentHashMap并发扩容)