Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

what's the equivalent of ThreadLocal of Java for C# ?

330 views
Skip to first unread message

UFO

unread,
May 14, 2010, 6:20:01 AM5/14/10
to
hello,

i would like to know how to use a similar feature that exist on Java, on my
C# program.
basically , the ThreadLocal allows you to decare&use a variable to be set
per thread, without the need to assign it from outside the thread itself.it
means that whoever uses the code doesn't even know that each thread he
creates , when it uses the class, it gets a new variable just for this thread.
for example, if i want to have a threadID , so that each new thread will
have a new number (from 0 , ascending) , i could use the next code on Java:

// Assigns unique contiguous ids to threads.
public class ThreadID
{
// The next thread ID to be assigned
private static AtomicInteger nextID =new AtomicInteger(0);
// My thread-local ID.
private static ThreadLocalID threadID =new ThreadLocalID();

// return unique ID for this thread
public static int get()
{
return threadID.get();
}

// Reset this thread's ID.the parameter is the index new ID
public static void set(int index)
{
threadID.set(index);
}

// Assign new IDs from zero.
public static void reset()
{
nextID.set(0);
}

public static int getNumberOfRegisteredThreads()
{
return nextID.get();
}

private static class ThreadLocalID extends ThreadLocal<Integer>
{
protected Integer initialValue()
{
return nextID.getAndIncrement();
}
}
}

so,for the first thread that uses this class by calling the 'get' function,
it will always (for all the next times that it calls this function) return 0.
for the second thread, it will always return 1 , and so on...

Alberto Poblacion

unread,
May 14, 2010, 7:29:01 AM5/14/10
to
"UFO" <U...@discussions.microsoft.com> wrote in message
news:60EF11FC-8CBF-4726...@microsoft.com...

> i would like to know how to use a similar feature that exist on Java, on
> my
> C# program.
> basically , the ThreadLocal allows you to decare&use a variable to be set
> per thread, without the need to assign it from outside the thread itself.


You can apply a ThreadStaticAttribute to a static variable:

[ThreadStatic]
static int value;


UFO

unread,
May 14, 2010, 5:25:01 PM5/14/10
to
to which variable ? the atomicInteger? if so,what about having a variable per
thread? if not, why should it be static?
can you please give me an example? maybe a way to do the same as what i've
written?
it's just that i've searched the internet for any example of how to do such
a thing and i didn't find even one.

Tom Shelton

unread,
May 14, 2010, 5:32:13 PM5/14/10
to
UFO explained :

It sounds as if your talking about TLS - thread local storage. Here is
an article that covers a bit about this on msdn:

http://msdn.microsoft.com/en-us/library/6sby1byh.aspx

It talks about thread relative static fields - which uses the
ThreadStaticAttribute and about dynamic tls using the various Thread
related tls functions (Thread.AllocateNamedDataSlot, etc).

HTH

--
Tom Shelton


UFO

unread,
May 15, 2010, 6:47:01 PM5/15/10
to
again, please give me a code example. it's a too important feature that there
is no example of how to use it.
please.

UFO

unread,
Jun 9, 2010, 4:58:07 PM6/9/10
to
it seems that dot net 4 has the ThreadLocal class:
http://msdn.microsoft.com/en-us/library/dd642243.aspx
that's a very good thing.
however,i wonder how one can use the same thing for dot net 3 . using other
methods like this one:
http://www.java2s.com/Tutorial/CSharp/0420__Thread/Usethreadlocalstorage.htm
or this:
http://msdn.microsoft.com/en-us/library/system.threading.thread.getnameddataslot.aspx
could work, but it makes the inner information to be public for all to read
and change , which is a bad thing for encapsulation.

Peter Duniho

unread,
Jun 10, 2010, 12:34:35 AM6/10/10
to

The [ThreadStatic] attribute has been present since .NET 1.0.

The new ThreadLocal class provides a mechanism to accomplish the same
thing for instance members, but there's always been a reasonably
convenient way to accomplish thread-local storage.

Pete

UFO

unread,
Jun 13, 2010, 4:59:19 AM6/13/10
to
not sure if i understand you. i do not need a static variable. i need to have
a variable that is per thread . each thread has its own instance of the
variable , and once the thread is gone (whatever the reason is) , its
variable is gone with it as well (only if there is no reference to it, of
course) .
i also do not want outer methods and threads to access one thread's variable
(unless i use some mechanism to overcome this) .

if you think that this is exactly what i need, please post a super short and
simple example. i suggest having the example that gives each new thread a
number (like an id ) that starts with the value 0 for the first thread, 1 for
the second , and so on .

Peter Duniho

unread,
Jun 13, 2010, 7:21:09 PM6/13/10
to
UFO wrote:
> not sure if i understand you. i do not need a static variable. i need to have
> a variable that is per thread .

The two are not mutually exclusive.

> each thread has its own instance of the
> variable , and once the thread is gone (whatever the reason is) , its
> variable is gone with it as well (only if there is no reference to it, of
> course) .

That's what [ThreadStatic] does.

> i also do not want outer methods and threads to access one thread's variable
> (unless i use some mechanism to overcome this) .

Protecting a variable from specific methods is simply a matter of
accessibility, as it is in any scenario, except of course that with
thread-local storage, you get automatic protection from any code not
executing in the thread with which the variable is associated.

And of course protecting the variable from other threads is exactly what
thread-local storage does, so that aspect is there by definition.

> if you think that this is exactly what i need, please post a super short and
> simple example. i suggest having the example that gives each new thread a
> number (like an id ) that starts with the value 0 for the first thread, 1 for
> the second , and so on .

I never said anything about the existing feature being "exactly what you
need". My point is that from a static thread-local variable, you can
construct any other thread-local data storage you need. Static members
come for free, that being exactly what [ThreadStatic] does, and instance
variables can be implemented on top of a static variable (e.g. with a
thread-local dictionary mapping instances to a value).

It's great that we now have an even more convenient way to have
thread-local instance variables in classes, but as I said before, it's
not like it was impossible, or even all that inconvenient, to implement
code that had thread-local instance-specific data storage in any
previous version of .NET.

Pete

UFO

unread,
Jun 14, 2010, 7:12:17 AM6/14/10
to
i don't get it. why does it called 'static' ?
also, does each instance garbage collected as soon as it is not referenced
(per thread) ?

and please, please give me an example of how it works.

Peter Duniho

unread,
Jun 14, 2010, 11:37:00 AM6/14/10
to
UFO wrote:
> i don't get it. why does it called 'static' ?

Because it's applicable only to static members. But that doesn't mean
you can't build data storage that's per-instance on top of that. You
just need an object that can map an instance to some specific data, and
then reference per-thread instances of that object in the static member.

An example of such an object would be a dictionary.

> also, does each instance garbage collected as soon as it is not referenced
> (per thread) ?

Since the static member is no longer present when the associated thread
no longer exists, everything it refers to is no longer reachable and can
be garbage-collected.

> and please, please give me an example of how it works.

Unfortunately, I don't have time to write a code sample now. Hopefully
the above is sufficient for you to understand the mechanism of how
per-instance, per-thread data storage would work using only the original
thread-local API in .NET.

Pete

UFO

unread,
Jun 17, 2010, 6:48:18 PM6/17/10
to
about the dictionary example, i don't get what is has to do with concurrency
and threads.

about static members, i still think that its name is misleading, since
static means that it can always be accessible and that there is only one
instance of it through the whole running time of the program.however,
'static' is also a misleading keyword on Java, since there you have a static
class, which is a very weird thing to have as a name for an inner class.on C#
, static clsss means it's like a Singleton , which is a little more obvious.

about the ThreadLocal (or static thread member ) , will it be garbage
collected as soon as the thread finishes its running? if so, will an inner
function of the thread (if i choose to extend the thread) be able to reach
such a member? or maybe threads cannot be extended (derived) just because of
this?

about a code example, you can copy and paste the one i gave, and change what
is needed to be changed.

Peter Duniho

unread,
Jun 18, 2010, 1:41:51 AM6/18/10
to
UFO wrote:
> about the dictionary example, i don't get what is has to do with concurrency
> and threads.

Because if you want per-instance thread-local data prior to .NET 4, you
need some mechanism to use the static-variable feature that exists to
implement an instance-variable feature that doesn't exist.

A dictionary isn't required, but it's the most obvious approach.

> about static members, i still think that its name is misleading, since
> static means that it can always be accessible and that there is only one
> instance of it through the whole running time of the program.however,
> 'static' is also a misleading keyword on Java, since there you have a static
> class, which is a very weird thing to have as a name for an inner class.on C#
> , static clsss means it's like a Singleton , which is a little more obvious.

The keyword "static" is being used in your code example in pretty much
the same way it's used in C#, with the exception of the static nested
class (which C# doesn't have the concept of...or rather, all nested
classes in C# are static nested; there are no inner classes).

So, no…in this case the word is not misleading at all. It's doing
exactly what one would expect even coming from C#, with the exception of
your static nested class.

In fact, since all your code involves static members, the [ThreadStatic]
attribute that has been around since .NET 1.0 is fine for the needs of
that sample.

> about the ThreadLocal (or static thread member ) , will it be garbage
> collected as soon as the thread finishes its running? if so, will an inner
> function of the thread (if i choose to extend the thread) be able to reach
> such a member? or maybe threads cannot be extended (derived) just because of
> this?

I don't know what you mean by "inner function". Even in Java, that's
not a defined term.

The System.Threading.Thread class is in fact sealed, so whatever
question you're asking with respect to inheriting (derived) classes, the
answer must be "you can't do that", because you can't inherit
System.Threading.Thread.

With respect to garbage collection of ThreadLocal, an instance of
ThreadLocal will follow the same rules as any other object. It's a
single instance, and will only be garbage collected when it's not
reachable at all. Note that when using ThreadLocal, all threads will
access the same instance of the object. The thing that makes it
per-thread is that the Value and IsValueCreated properties access data
storage that is specific to each thread.

So, if you are storing a reference type in the ThreadLocal object, when
the thread for a Value of that reference type no longer exists, then in
theory that Value for that thread is no longer reachable, even though
the ThreadLocal object itself is still reachable and could be eligible
for garbage collection.

> about a code example, you can copy and paste the one i gave, and change what
> is needed to be changed.

I don't think copy/paste of Java code is going to help much. But here
are some examples of how you might have thread-local storage, static and
per-instance (warning: uncompiled, untested code…I apologize in advance
for any silly typos or minor structural defects, but the basic idea
should be correct):

// Using static member, only provides static
// thread-local data
public class ThreadID
{
private static volatile int nextID = 0;

[ThreadStatic]
private static int threadID = Interlocked.Increment(ref nextID);

public static int get()
{
return threadID;
}

public static void set(int index)
{

threadID = index;
}

public static void reset()
{
nextID = 0;
}

public static int getNumberOfRegisteredThreads()
{
return nextID;
}
}


// Using static dictionary to implement per-instance
// thread-local data
public class ThreadID
{
private static volatile int nextID = 0;

[ThreadStatic]
private static Dictionary<ThreadID, int> _dictThreadID =
new Dictionary<ThreadID, int>();

public ThreadID()
{
_dictThreadID.Add(this, Interlocked.Increment(ref nextID));
}

public int get()
{
return _dictThreadID[this];
}

public void set(int index)
{
_dictThreadID[this] = index;
}

public static void reset()
{
nextID = 0;
}

public static int getNumberOfRegisteredThreads()
{
return nextID;
}
}


// Using ThreadLocal class to implement per-instance
// thread-local data (.NET 4.0 only)
{
private static volatile int nextID = 0;
private static ThreadLocal<int> threadID = new ThreadLocal<int>();

public ThreadID()
{
threadID.Value = Interlocked.Increment(ref nextID);
}

public int get()
{
return threadID.Value;
}

public void set(int index)
{
threadID.Value = index;
}

public static void reset()
{
nextID = 0;
}

public static int getNumberOfRegisteredThreads()
{
return nextID;
}
}


Hope that helps.

Pete

Peter Duniho

unread,
Jun 18, 2010, 1:46:48 AM6/18/10
to
And speaking of structural defects…

Peter Duniho wrote:
> [...]


> // Using ThreadLocal class to implement per-instance
> // thread-local data (.NET 4.0 only)
> {
> private static volatile int nextID = 0;
> private static ThreadLocal<int> threadID = new ThreadLocal<int>();

Of course, for "threadID" to store data per-instance, it must be an
instance variable, not "static" as I've declared above. Sorry for the
mistake.

Peter Duniho

unread,
Jun 18, 2010, 2:27:11 AM6/18/10
to
Okay, one more try (I did warn that the code hadn't been compiled, never
mind tested :) )…

Anyway, both of the per-instance examples I posted have a fundamental
flaw in that they initialize the value only for the thread where the
instance is created. Other threads won't have values when they attempt
to read the per-instance thread-local value.

Here are fixed versions:

// Using static dictionary to implement per-instance
// thread-local data
public class ThreadID
{
private static volatile int nextID = 0;

[ThreadStatic]
private static Dictionary<ThreadID, int> _dictThreadID =
new Dictionary<ThreadID, int>();

public int get()
{
int i;

if (!_dictThreadID.TryGetValue(this, out i))
{
i = Interlocked.Increment(ref nextID);
_dictThreadID.Add(this, i);
}

return i;
}

public void set(int index)
{
_dictThreadID[this] = index;
}

public static void reset()
{
nextID = 0;
}

public static int getNumberOfRegisteredThreads()
{
return nextID;
}
}


// Using ThreadLocal class to implement per-instance
// thread-local data (.NET 4.0 only)
{
private static volatile int nextID = 0;

private ThreadLocal<int> threadID =
new ThreadLocal<int>(() => Interlocked.Increment(ref nextID));

public int get()
{
return threadID.Value;
}

public void set(int index)
{
threadID.Value = index;
}

public static void reset()
{
nextID = 0;
}

public static int getNumberOfRegisteredThreads()
{
return nextID;
}
}

Note that in both cases, the value is not initialized until the first
access. This means that the int ID returned may or may not correlated
to the order in which any thread was created, depending on when the ID
value is actually retrieved or set.

Of course, since a per-instance value isn't really correlated per-thread
anyway (for any given thread, there will be N unique IDs where N is the
number of instances of ThreadID created), this shouldn't be much of an
issue. The main point here is to show how the techniques work.

I _believe_ that I have finally worked out the wrinkles in the examples
I posted. But I'm still too lazy to actually compile and run the code
at the moment, so if there are still problems, I do apologize for that. :)

Pete

0 new messages