.NET Forum / Languages / C# / November 2004
Threadsafe value types
|
|
Thread rating:  |
John - 06 Nov 2004 17:42 GMT 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
Thomas P. Skinner [MVP] - 06 Nov 2004 18:57 GMT 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]
> 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 [quoted text clipped - 16 lines] > > John John - 06 Nov 2004 20:34 GMT 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?
>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 [quoted text clipped - 31 lines] >> >> John Thomas P. Skinner [MVP] - 06 Nov 2004 23:02 GMT 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]
> Hi Thomas, > [quoted text clipped - 53 lines] >>> >>> John Jon Skeet [C# MVP] - 07 Nov 2004 18:17 GMT <snip>
> 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
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Thomas P. Skinner [MVP] - 07 Nov 2004 19:43 GMT 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]
> <snip> > [quoted text clipped - 9 lines] > > See http://www.pobox.com/~skeet/csharp/threads/volatility.shtml Jon Skeet [C# MVP] - 08 Nov 2004 08:14 GMT > 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.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Jeff Louie - 07 Nov 2004 00:40 GMT 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; } } }
John - 07 Nov 2004 10:11 GMT 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
> John... As Thomas suggested if you declare the variable readonly the > compiler appears to block setters in the structure. [quoted text clipped - 46 lines] > } > } Jeff Louie - 07 Nov 2004 22:10 GMT 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
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|