The Joel on Software Discussion Group (CLOSED)

A place to discuss Joel on Software. Now closed.

This community works best when people use their real names. Please register for a free account.

Other Groups:
Joel on Software
Business of Software
Design of Software (CLOSED)
.NET Questions (CLOSED)
TechInterview.org
CityDesk
FogBugz
Fog Creek Copilot


The Old Forum


Your hosts:
Albert D. Kallal
Li-Fan Chen
Stephen Jones

Serialization required?

Supposed I have this class:

class Foo
{
    static ConfigData s_configData;
    public void Refresh()
    {
        configData = new ConfigData();
        configData.Initialize(); // time consuming
        s_configData = configData;
    }
    public ConfigData GetConfigData()
    {
        return s_configData;
    }
}

This is an ASP.NET (multi-threaded) environment where Refresh is called by a thread that periodically refreshes the configuration data.

Assume that Refresh is called when the application initially starts already.

Assume that the client do not have an urgent need to be accessing the most current ConfigData. That is, while the ConfigData.Initialize method is completing, the client can happily work with old ConfigData information.

Do I need to protect access to s_configData variable with a lock method to prevent situations where I'm accessing a pointer whose address value is not completely populated yet or is .NET pointer management system smart enough to make the pointer assignment an atomic operation such that when I return that pointer, I will not get an incomplete memory address? (I assume that this was a problem with C++).
Binh
Thursday, July 12, 2007
 
 
I'm not familiar with dotnet's memory model, but I would assume no, you would not get an incomplete memory address.  If you found a definitive answer though, I'm interested in hearing it.
Anon Send private email
Thursday, July 12, 2007
 
 
First of all, let me say that I am not an expert on the .NET memory model. But I will try to answer your question anyways.

The pointer assignment will most likely be an atomic operation on current x86-hardware, but you still have a problem. The compiler and processor are both allowed to reorder load and store operations. Therefore it may happen, that the store operation that assigns s_configData is done, before the initialization of configData is complete. This is usually not a problem in the single-threaded case, but in a multi-threaded setting it means other threads may see an incomplete version of s_configData. This will most likely not happen on x86-hardware as far as I know, because its memory model is stronger than the .NET-one. You can also try to prevent things like that from happening by using volatile or memory fences.

But please don't. I have written an article about (not) using memory barriers for synchronisation in the past here:
http://www.thinkingparallel.com/2007/02/19/please-dont-rely-on-memory-barriers-for-synchronization/

I still think its a bad idea, except if you are a compiler writer or eat assembly for breakfeast. Just start with using locks, you will most likely not see a drop in performance anyways, because uncontended locks are quite fast today. If your profiler tells you the locks are a problem, be sure to read up on the .NET memory model before trying to get rid of them, e.g. here:
http://blogs.msdn.com/cbrumme/archive/2003/05/17/51445.aspx

And good luck, because this is really low-level and complicated stuff that takes years of experience to get right. And even if you can get it right, I bet the programmer who ends up maintaining your code cannot...
Michel Suess Send private email
Thursday, July 12, 2007
 
 
"that the store operation that assigns s_configData is done, before the initialization of configData is complete."

I'm not sure thats correct, because as you see, he's assigning it to a temp variable first.  I don't see how it would break...
Anon Send private email
Thursday, July 12, 2007
 
 
The blind leading the blind...

Friday, July 13, 2007
 
 
Assigning to a temp variable first does not help. The compiler/processor is technically allowed to make the order of operations appear to others threads like this:

public void Refresh()
{
    configData = new ConfigData();
    s_configData = configData;
    configData.Initialize(); // time consuming
}

Other threads may therefore see an uninitialized or incompletely initialized version.
Michael Suess Send private email
Friday, July 13, 2007
 
 
Michael, thanks for the response. I am currently reading yoru blog.  Good stuff.
Anon Send private email
Friday, July 13, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz