alibaba / transmittable-thread-local

📌 a missing Java std lib(simple & 0-dependency) for framework/middleware, provide an enhanced InheritableThreadLocal that transmits values between threads even using thread pooling components.
https://github.com/alibaba/transmittable-thread-local
Apache License 2.0
7.35k stars 1.67k forks source link

关于快照与实时获取的ttlMap存在差异的删除逻辑 可能存在风险。 #665

Open shaobocui opened 2 weeks ago

shaobocui commented 2 weeks ago

public static Object replay(Object captured) 这里replay的时候,

Map<TransmissibleThreadLocal<?>, Object> capturedMap = (Map)captured; Map<TransmissibleThreadLocal<?>, Object> backup = new HashMap(); Iterator<? extends Map.Entry<TransmissibleThreadLocal<?>, ?>> i$ = ((Map)TransmissibleThreadLocal.holder.get()).entrySet().iterator(); // 这是子线程获取的最新的 ttlMap

        Map.Entry entry;
        TransmissibleThreadLocal threadLocal;
        while(i$.hasNext()) {
            entry = (Map.Entry)i$.next();
            threadLocal = (TransmissibleThreadLocal)entry.getKey();
            backup.put(threadLocal, threadLocal.get());
            if (!capturedMap.containsKey(threadLocal)) { // 如果快照中没有某个 ttl,居然要从holder中删除这不是很危险么。
           // 假如当前执行这个代码的线程A,它获取到的ttl快照的时候。有10个ttl变量。从holder中再次读取的时候,是11个ttl变量。
           // 这个Iterator要把当前最新holder中多出来的ttl删除 这是什么逻辑?
                i$.remove();
                threadLocal.superRemove();
            }
        }
shaobocui commented 2 weeks ago

ttl是lazy(只有被设置值的时候才会加到holder中)模式添加到holder当中的。当前某个线程在获取 holder ttlMap快照的时候 很可能有其他的 ttl 还没有设置过值,假如正好在 上下文拷贝的时候 holder 的map 中新增了 ttl 。 这个时候 在 replay 过程中 会把 holder 中的ttl 错误的删除掉。不理解 if (!capturedMap.containsKey(threadLocal)) { // 如果快照中没有某个 ttl,居然要从holder中删除这不是很危险么。 i$.remove(); threadLocal.superRemove(); } 不太能理解这三行代码的作用。没有貌似也没有问题。只是缺少一种清理 holder 的手段? holder本身是weakHashMap.