关于多线程环境下对象销毁代码正确性的验证请求
Great catch on this potential race condition! Let me walk through why your fix is exactly the right approach here.
The Problem with the Original Code
First, let's recap the issue in the original implementation. Here's the code for reference:
private queryBag : IQueryBag ... ... ... private function destroyQueryBag() : Void { CoreThread.transferToCoreThread(function() { if (queryBag != null) { queryBag.destroy(); queryBag = null; } }); } private function resetRequestsAndResponses() : Void { destroyQueryBag(); queryBag = null; queryBag = createNewQueryBag(); }
The critical race condition here is that the background thread's destruction logic runs asynchronously. If createNewQueryBag() completes before the background thread executes queryBag.destroy(), the queryBag variable will already point to a new object. This means two problematic outcomes:
- The original
queryBaginstance is never destroyed (it's lost, leading to memory leaks) - The destruction operation becomes ineffective because it's targeting the wrong object entirely
Your Fix: Correct and Robust
Your modified code fixes this perfectly by using a temporary reference to capture the original queryBag before any other changes happen. Here's the optimized code again:
private var queryBag : IQueryBag ... ... ... private function destroyQueryBag() : Void { var tempQueryBag = queryBag; // Capture the current reference queryBag = null; CoreThread.transferToCoreThread(function() { if (tempQueryBag != null) { tempQueryBag.destroy(); tempQueryBag = null; } }); } private function resetRequestsAndResponses() : Void { destroyQueryBag(); queryBag = createNewQueryBag(); }
Why this works:
- You lock in the original reference immediately: By assigning
tempQueryBag = queryBagfirst, you capture the exact instance that needs destruction, no matter what happens to thequeryBagvariable later. - You isolate the background thread from subsequent changes: Nulling out
queryBagright away ensures that the new instance created bycreateNewQueryBag()never gets tangled up with the destruction logic. The background thread only operates on the temporary reference to the old object. - Eliminates the race condition entirely: The background thread will always destroy the correct instance, even if
resetRequestsAndResponses()moves on to create a newqueryBagimmediately.
A minor note: Depending on your language's memory model, you might want to ensure proper visibility of the temporary reference across threads, but in most cases (especially with closure capture like this), this is handled automatically. Your core fix is solid and addresses the root of the problem.
内容的提问来源于stack exchange,提问作者OVelychko

