This is actually a non-blocking memory recovery problem that was explored many years ago when Maged Michael, one of the authors of the MS lineup, introduced hazard pointers [1].
Hazard pointers allow a thread to reserve blocks so that other threads do not actually return them until completion. However, this mechanism leads to non-trivial performance overheads.
There are also many epoch-based reclamation options, such as RCU [2,3], and more recently, interval-based reclamation (IBR) [4]. They avoid use after release, reserving ages, and are faster than hazard indicators. As far as I know, remediation of the era is widely used to solve this problem.
You can take a look at these documents below for more details. The article "Interval-based memory recovery" discusses a lot.
This is a common problem in non-blocking data structures, and we, as a rule, do not consider it as an error of the data structure itself - after all, this happens only in languages ββthat use manual memory management, such as C / C ++, but not in Java (by the way, Michael & Scott Queue has been used in Java Concurrency for many years).
Reference:
[1] Hazard statements: secure memory recovery for non-blocking objects, Maged M. Michael, IEEE Transactions in Parallel and Distributed Systems, 2004
[2] Memory recovery performance for synchronization without blocking, Thomas E. Hart et al., Journal of Parallel and Distributed Computing, 2007
[3] Read Copy Update, Paul E. McKenney et al., Ottawa Linux Symposium, 2002.
[4] Interval-based memory recovery, Khaosen Wen et al., Materials of the 23rd ACM SIGPLAN Symposium on the Principles and Practices of Parallel Programming (PPoPP), 2018.