Threadsafe value types

  • Thread starter Thread starter John
  • Start date Start date
J

John

If a value type is immutable, I guess it's threadsafe to read it? But not
threadsafe to assign a new value to it (can any value type be truely
immutable? Isn't assigning a totally new value to it, like doing an
modification, when no references are involved? I don't know enough about
CLR)

At the moment the whole:

lock(anobject)
{
threadsafevar = new something(1,2,3,4,5); // is this needed for both value
and ref types?
}

Is fine, but it would be really good be able to *require* that a particular
variable was locked before access.

Thanks,

John
 
I am not sure I know what you mean by immutable in this context. Strings are
immutable by virtue of the fact that if you try to assign to a string a new
string is created. This means a new reference is generated. Value types like
int etc. can be made readonly and can't be assigned to once initialized.

As far as I know there is absolutely no way to force a programmer to use
lock. You should also be aware that the volatile keyword should be used
with fields used with multi-threaded applications to prevent compiler
optimizations that cause caching and hence problems regardless of the use of
the lock. If something is accessed in more than one thread it make no
difference if it is a value or reference type.

Thomas P. Skinner [MVP]
 
Hi Thomas,

There seem to me many types I can't make volatile.. including any structs
I've made, and DateTimes!

I thought lock() removed the need for 'volatile'?

By immutable value types I meant ones like DateTime, where you can't alter
fields / properties, except by creating a new instance. This seems to be
seen as 'a good thing' by the C# boffins at Microsoft. That whiteboard
lecture on MSDN TV certainly indicated it was (I need to get out more).

However, with my limited understanding of CLR, I would have thought that:

DateTime a = new DateTime(1970,1,1);
....
a = new DateTime(1971,1,1);

is actually breaking the immutability of 'a'. It's a value type, so are we
effectively changing it by doing something like 'year = 1971'? Or would the
old 'a' still exist somewhere until it's GCed?
 
You are correct. A struct can't be made volatile. Any reference type can as
well as various ints, floats, char and enum. They must be fields however.

As to your example, Just make it readonly. Consider this:

int i=1;
int i=2;

i is not immutable, but the 1 and the 2 are. Same thing with DateTime.

Thomas P. Skinner [MVP]
 
John... As Thomas suggested if you declare the variable readonly the
compiler appears to block setters in the structure.

Regards,
Jeff
If a value type is immutable, I guess it's threadsafe to read it? But
not threadsafe to assign a new value to it(can any value type be truely
immutable?<

====== code =============

using System;

namespace TestStruct
{
public struct MutableS
{
private int i;
public int I
{
get {return i;}
set {this.i= value;}
}
public MutableS(int i)
{
this.i=i;
}
}

/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
static readonly MutableS ro_sm= new MutableS(1);
static MutableS sm= new MutableS(2);
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
//Class1.ro_sm.I= 3; // will not compile!
Class1.sm.I= 4;
}
}
}
 
Thanks for the help guys.

So is there no added value in having a create-only value type like DateTime,
that doesn't give write access to it's fields / properties?

MSDN gives the impression struct's that allow field modification are bad -
but I can't see why if these two are equivelent:

// editable struct instance
DateTime a = new DateTime(1970,1,1);
a.ChangeDay(2); // a fictional method I made up to alter the
DateTime struct!

....and...

// new struct instance
DateTime a = new DateTime(1970,1,1);
a = new DateTime(1970,1,2);

Would these be functional equivelent?

John

Jeff Louie said:
John... As Thomas suggested if you declare the variable readonly the
compiler appears to block setters in the structure.

Regards,
Jeff
If a value type is immutable, I guess it's threadsafe to read it? But
not threadsafe to assign a new value to it(can any value type be truely
immutable?<

====== code =============

using System;

namespace TestStruct
{
public struct MutableS
{
private int i;
public int I
{
get {return i;}
set {this.i= value;}
}
public MutableS(int i)
{
this.i=i;
}
}

/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
static readonly MutableS ro_sm= new MutableS(1);
static MutableS sm= new MutableS(2);
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
//Class1.ro_sm.I= 3; // will not compile!
Class1.sm.I= 4;
}
}
}
 
You should also be aware that the volatile keyword should be used
with fields used with multi-threaded applications to prevent compiler
optimizations that cause caching and hence problems regardless of the use of
the lock.

That's not true. Acquiring a lock involves a volatile read, and
releasing it involves a volatile write, so volatility isn't required if
you're using locks appropriately.

See http://www.pobox.com/~skeet/csharp/threads/volatility.shtml
 
This is a good point but the use of a lock does not actually eliminate the
compiler or runtime from optimizations on fields not marked as volatile.
Sure, if all accesses are inside the locked block then there would be no
problems in practice. But having knowledge of the existence of the volatile
modifier is certainly worthwhile.

Thomas P. Skinner [MVP]
 
John....>So is there no added value in having a create-only value type
like
DateTime, that doesn't give write access to it's fields / properties?<

A very good question. Most would not argue about the advantages of using
immutable classes. The advantages for immutable structures are less
obvious
since they use value semantics and provide automatic "defensive copies."
Still
immutable structures are going to be simple, reliable and useful for
building
complex objects.

Let me turn the question around. Since most structures are simple small
constructs that are easily passed and copied using value semantics, why
not
simplify your life/code and write only immutable structures? A typical
method
might take an "instance" of a value type and return a different
"instance" of
the same value type or just it may just read the value. So a typical
method
would not need access to any setters outside of initialization which can
be
done in the constructor.

So immutable structures are simpler and more reliable than mutable
structures, but may be harder to initialize since you must know the
proper
order to pass the arguments to the constructor as opposed to using named
setters.
// editable struct instance
DateTime a = new DateTime(1970,1,1);
a.ChangeDay(2); // a fictional method I made up to alter the
DateTime struct!

....and...

// new struct instance
DateTime a = new DateTime(1970,1,1);
a = new DateTime(1970,1,2);

Would these be functional equivelent?<

In the sense that the containing object's state is mutated either way,
yes. So
to _build_ a immutable class (as opposed to using a immutable class) "a"
should be private. You can do anything you want within the class as long
as
no method makes an externally visible change in the objects state and
the
object does not violate an invariant for which it is responsible.

Regards,
Jeff
 
Thomas P. Skinner said:
This is a good point but the use of a lock does not actually eliminate the
compiler or runtime from optimizations on fields not marked as volatile.

Not outside the lock, no. But then if you're using locks in some
places, you almost certainly shouldn't be accessing the variables
without acquiring a lock in *all* places anyway. There's no need to use
the volatile modifier to achieve thread safety, contrary to the
statement in your earlier post.
Sure, if all accesses are inside the locked block then there would be no
problems in practice.

And none in theory either. If we were only talking about "in practice"
scenarios, there's an awful lot you can get away with which I wouldn't
recommend.
But having knowledge of the existence of the volatile
modifier is certainly worthwhile.

Undoubtedly, although I prefer not to use volatile fields myself, using
locks instead.
 
Back
Top