Skip to content

fix(profile-ex): 修复并发创建重复 ProfileExItem 的问题 - #10420

Merged
2dust merged 1 commit into
2dust:masterfrom
Nozilla-X:fix/profileexmanager-get-or-add
Oct 20, 2026
Merged

2dust merged 1 commit into
2dust:masterfrom
Nozilla-X:fix/profileexmanager-get-or-add

Conversation

@Nozilla-X

Copy link
Copy Markdown
Contributor

问题

在 ProfileExManager.GetProfileExItem() 中,当前逻辑是:

_lstProfileEx.FirstOrDefault(t => t.IndexId == indexId) ?? AddProfileEx(indexId)

虽然 _lstProfileEx 使用的是 ConcurrentBag,但“查找是否存在”与“创建新项”是两个独立操作,并不是原子的。

当多个线程同时处理相同 IndexId 时,可能出现多个线程同时判断该项不存在,随后分别调用 AddProfileEx(),最终导致同一个 IndexId 出现多个 ProfileExItem。

这个问题会导致:

ProfileExManagerConcurrencyTests.SetTestDelay_ShouldCreateOneEntryPerIndex

出现随机失败,例如:

  • Expected 10, found 11
  • Expected 10, found 13

该问题是在最近 WebAPI CI 增加 ServiceLib 回归测试后暴露出来的,但实际问题位于原有 ProfileExManager 并发逻辑中,与 WebAPI 本身无关。

修改

见文件

验证

Nozilla-X@ea25ff3

ConcurrentBag only makes individual operations safe. GetProfileExItem performed FirstOrDefault and AddProfileEx as separate operations, so concurrent speed tests could both miss and create duplicate entries for the same IndexId. Recheck under a dedicated lock before creating, and replace the bag under the same lock in InitData/ClearAll so creation cannot target a bag that is being swapped. Existing reads and item updates stay lock-free.
@Nozilla-X Nozilla-X closed this Oct 20, 2026
@Nozilla-X
Nozilla-X deleted the fix/profileexmanager-get-or-add branch October 20, 2026 06:36
@Nozilla-X
Nozilla-X restored the fix/profileexmanager-get-or-add branch October 20, 2026 06:37
@Nozilla-X Nozilla-X reopened this Oct 20, 2026
patterniha pushed a commit to patterniha/PattN that referenced this pull request Oct 20, 2026
@2dust
2dust merged commit 57f17d5 into 2dust:master Oct 20, 2026
20 checks passed
@aleksandr-miheichev

Copy link
Copy Markdown
Contributor

For reference, I opened #10410 on October 18 to address the same ProfileExManager race, including regression tests. Since #10420 now covers the production fix, I have rebased #10410 and retained only the additional regression coverage. Linking the two PRs here to make the earlier work and remaining tests easy to find.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants