Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Wrong Answer #3: Your own Thread Local

DZone's Guide to

Wrong Answer #3: Your own Thread Local

·
Free Resource

Last time, we forgot that the slots dictionary is a thread static variable, and that the finalizer is going to run on another thread… Let us fix this, too:

public class CloseableThreadLocal
{
[ThreadStatic]
public static Dictionary<object, object> slots;

private readonly object holder = new object();
private Dictionary<object, object> capturedSlots;

private Dictionary<object, object> Slots
{
get
{
if (slots == null)
slots = new Dictionary<object, object>();
capturedSlots = slots;
return slots;
}
}


public /*protected internal*/ virtual Object InitialValue()
{
return null;
}

public virtual Object Get()
{
object val;

if (Slots.TryGetValue(holder, out val))
{
return val;
}
val = InitialValue();
Set(val);
return val;
}

public virtual void Set(object val)
{
Slots[holder] = val;
}

public virtual void Close()
{
GC.SuppressFinalize(this);
if (capturedSlots != null)
capturedSlots.Remove(this);
}

~CloseableThreadLocal()
{
if (capturedSlots == null)
return;
capturedSlots.Remove(holder);
}
}

And now it works!

Except… Under some very rare scenarios, it will not do so.

What are those scenarios? Why do we care? And how do we fix this?

Topics:

Published at DZone with permission of Oren Eini, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}