Subj : Re: double-checked locking in C To : comp.programming.threads From : Laurent Deniau Date : Wed Jul 06 2005 03:33 pm David Schwartz wrote: > "Laurent Deniau" wrote in message > news:dagh6d$s9j$1@sunnews.cern.ch... > > >>This is done by the mutext lock and unlock. > > > Except that threads may never lock the mutex. So there's no way to > guarantee they'll ever see the initialization. > > >>They unsure synchronization of the memory content with other threads >>(otherwise mutex would be completely useless). > > > Yes, but not when you don't call them. > > >>I do not have to deal with such problem > > > Yes, you do. POSIX requires you to. > > >>(and it is not possible at the level of C). > > > Bingo. > > >>>There was nothing in your example showing that the initialization stores >>>had to appear in memory before the store to the init flag did. > > >>This is the problem of unlock, not mine. Between the lock/unlock I *only* >>must ensure that if other threads see a value in the first test (by a >>premature memory commit), it is a valid value, which by the way never >>change after being set. The rest is done by lock/unlock. > > > The problem is, you don't call 'lock' or 'unlock' if the initialization > has already been done. So there's no way to ensure that you actually see the > initialized values. > > >>Remember the context: C language, singleton pattern (or unique >>initialization) and DCL. Nothing more. >> >>If you still see a problem in my code, please show me a sequence of >>actions (sequence points) done by two (or more) threads which breaks the >>semantic of the singleton pattern. > > > Here goes: > > >>>bool initialized = false; >>>pthread_mutex_t mutex; >>> >>>void function(void) >>>{ >>> if (!initialized) { >>> pthread_mutex_lock(&mutex); >>> if (!initialized) { >>> initialized = true; >>> init_code(); >>> } >>> pthread_mutex_unlock(&mutex); >>> } >>>} > > > Let's add: > > int i=0; > void init_code(void) { i=1; } > > Here's the problem: > > Thread 1: Calls function. Calls init_code. Locks and unlocks mutex. > > Thread 2: Calls function. Sees 'initialized' as true. Does not lock or > unlock mutex. Sees 'i' as '0'! Oops. Right. But this is not what I say. I was talking about value of initialized before and after lock. It is clear that if extern_init_code() has some side effects, it must lock/unlock the ressource it deals with otherwise you break the semantic. For example if initialized is a pointer to a singleton instance and extern_init_code() is a factory calling malloc, you do not need a mutex, but malloc will certainly use one internally. Therefore the correct code is (assuming a different translation unit): int i=0; pthread_mutex_t init_mutex; int extern_init_code(void) { pthread_mutex_lock(&init_mutex); i=1; pthread_mutex_unlock(&init_mutex); return 1; } ld. .