Thread-safe statické proměnné bez mutexing?

hlasů
13

Vzpomínám si četl, že statické proměnné deklarované uvnitř metod není thread-safe. (Viz A co Meyerova jedináček? Jak uvádí Todd Gardner )

Dog* MyClass::BadMethod()
{
  static Dog dog(Lassie);
  return &dog;
}

Moje knihovna generuje kódu jazyka C ++ pro koncoví uživatelé sestavit jako součást své žádosti. Kód generuje potřebuje k inicializaci statické proměnné v cross-platform způsobem thread-safe. Já bych chtěl využít boost::call_oncek mutex variabilní inicializace ale koncovým uživatelům jsou vystaveny závislost podporu.

Existuje způsob, jak pro mě, jak to udělat, aniž by nutit další závislostí na koncové uživatele?

Položena 27/06/2009 v 06:30
zdroj uživatelem
V jiných jazycích...                            


5 odpovědí

hlasů
10

Máte pravdu, že statická inicializace takového není závit bezpečné ( zde je článek, diskutovat o tom, co bude kompilátor proměnit)

V tuto chvíli neexistuje žádný standard, závit bezpečné, přenosné způsob inicializace statické singletons. Double zkontrolovat zamykání může být použit, ale je třeba potenciálně nepřenosné threading knihovny (viz diskusi zde ).

Zde je několik možností, pokud bezpečnostní vlákno, je třeba:

  1. Nebuďte líní (naložený): Inicializace během statické inicializaci. Mohlo by to být problém, pokud jiné statické volání této funkce v jeho konstruktoru, protože pořadí statické inicializaci je definována (viz zde ).
  2. Použijte podporu (jak jste uvedl), nebo Loki
  3. Vytvořit vlastní Singleton na svých podporovaných platformách (třeba pravděpodobně vyhnout, pokud jste závitů expert)
  4. Zamknout mutex pokaždé, když potřebují přístup. To by mohlo být velmi pomalé.

Příklad 1:

// in a cpp:
namespace {
    Dog dog("Lassie");
}

Dog* MyClass::BadMethod()
{
  return &dog;
}

Příklad 4:

Dog* MyClass::BadMethod()
{
  static scoped_ptr<Dog> pdog;
  {
     Lock l(Mutex);
     if(!pdog.get())
       pdog.reset(new Dog("Lassie"));
  }
  return pdog.get();
}
Odpovězeno 27/06/2009 v 06:55
zdroj uživatelem

hlasů
4

Nejste si jisti, zda je to to, co máte na mysli, nebo ne, ale můžete odstranit závislost zesílení na POSIX systémech voláním pthread_oncemísto. Myslím, že budete muset dělat něco jiného na Windows, ale vyhnout to je přesně důvod, proč boost má knihovnu niti na prvním místě, a proč lidé zaplatí cenu v závislosti na něm.

Dělat něco „thread-bezpečný“ je neodmyslitelně spjato s realizací závity. Budete muset záviset na něčem , i když je to jen na platformě závislá paměť modelu. Je to prostě není možné v čistě C ++ 03 předpokládat, vůbec nic o závity, které jsou mimo rozsah tohoto jazyka.

Odpovězeno 27/06/2009 v 10:55
zdroj uživatelem

hlasů
3

Jeden způsob, jak byste mohli udělat, který nevyžaduje mutex pro bezpečnost závitu je, aby ojedinělým soubor statický, spíše než funkce statické:

static Dog dog("Lassie");
Dog* MyClass::BadMethod()
{
  return &dog;
}

DogInstance bude inicializovat před hlavními závitových běhů. Soubor statické proměnné mají slavnou problém s pořadí inicializace, ale tak dlouho, dokud pes není závislý na jiných statiky definovaných v jiném jednotce překlad, nemělo by to být problém.

Odpovězeno 27/06/2009 v 06:47
zdroj uživatelem

hlasů
2

Pokud vím, jediný případ, kdy to bylo provedeno bezpečně a bez mutexy nebo předchozího inicializace globálních případů je v Matthewa Wilsona Imperfect C ++ , který popisuje, jak to provést pomocí „spin mutex“. Nejsem poblíž mého kopii, takže vám nemohu říci nic víc, právě v tomto okamžiku.

IIRC, tam jsou některé příklady využití tohoto uvnitř STLSoft knihoven, ale nemůžu si vzpomenout, jaké komponenty v tomto okamžiku.

Odpovězeno 27/06/2009 v 07:36
zdroj uživatelem

hlasů
2

Jediný způsob, jak vím, aby byla zaručena nebudete mít threading problémy s nechráněných zdrojů jako bys "static Dog"je, aby to požadavek, že všichni jsou vytvořena před jsou vytvořeny nějaké nitě.

Mohlo by to být tak jednoduché, jak jen dokumentuje, že musí zavolat MyInit()funkci v hlavním vlákně, než dělat něco jiného. Pak můžete postavit MyInit()k vytvoření instance a zničit jeden objekt od každého typu, který obsahuje jednu z těch statiky.

Jedinou další možností je dát další omezení na to, jak mohou využít svůj vygenerovaný kód (použití pro upřednostnění, Win32 nitě, atd). Kterýkoliv z těchto řešení jsou přijatelné podle mého názoru - je to v pořádku, aby vytvářet pravidla, která musí následovat.

Pokud tomu tak není podle pravidel, stanovených v dokumentaci, pak jsou všechny sázky jsou pryč. Pravidlo, že musí volat inicializační funkce nebo být závislý na Boost, není od věci se mi.

Odpovězeno 27/06/2009 v 06:43
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more