2009-06-27 18 views
13

Yöntemler içinde bildirilen statik değişkenlerin thread güvenli olmadığını okumayı hatırlıyorum.Sızdırmazlık olmadan diş güvenli statik değişkenler?

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

My kitaplıkta başvurunun bir parçası olarak derlemek için son kullanıcı için C++ kodu üretir (Todd Gardner tarafından belirtildiği gibi What about the Meyer's singleton? bakınız). Oluşturduğu kod, statik değişkenleri çapraz-güvenli çapraz platform biçiminde başlatmaya ihtiyaç duyar.değişken değişkeni muteks olarak kullanmak istiyorum ama son kullanıcılar Boost bağımlılığına maruz kalıyor.

Son kullanıcılara fazladan bağımlılık yapmadan bunu yapmanın bir yolu var mı?

+0

Ayrıca statik o zaman kullanıcılarını tatbikî korkusu olmadan istediğin boost kullanabilirsiniz, kendi içine boost kütüphanelerde bağlayabilirsiniz. – Ben

+0

olası yinelenen [C++ 11'de yerel statik değişken başlatma ipliği güvenli midir?] (Http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11) –

+1

@LucianAdrianGrijincu, bu soru C++ 11 (2009'da yayınlanmıştır) öncesine göre sorunuzu alakalı olmasına rağmen katı bir kopya değildir. Bağlantı için teşekkürler. * * Ikamet gelmez D – Gili

cevap

10

Sen başlatmak için hiçbir standart, iplik güvenli, taşınabilir yol var, Şu anda

(here derleyici çevirmek ne tartışan bir makale) böyle statik başlatma parçacığı güvenli olmadığını doğru Statik singletonlar. Çifte kontrol edilen kilitleme kullanılabilir, ancak potansiyel olarak portatif olmayan diş açma kitaplıklarına ihtiyacınız vardır (bkz. Bir tartışma here).

  1. Tembel olmayın (yüklü): statik başlatma sırasında başlat parçacığı güvenliği bir zorunluluktur eğer

    İşte birkaç seçenek var. Statik başlatmanın sırası tanımlanmamış olduğundan (bkz. here) başka bir statik, bu işlevi yapıcıda çağırırsa bir sorun olabilir.Desteklenen platformlar üzerinde

  2. kullanımı (dediğin gibi) artırmak veya Loki
  3. Rulo sizin kendi tekil
  4. Lock erişmesi gereken bir muteks her (muhtemelen sürece bir iş parçacığı uzmanı olan kaçınılmalıdır). Bu çok yavaş olabilir.

Örnek 1 için:

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

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

Örnek 4 için:

Dog* MyClass::BadMethod() 
{ 
    static scoped_ptr<Dog> pdog; 
    { 
    Lock l(Mutex); 
    if(!pdog.get()) 
     pdog.reset(new Dog("Lassie")); 
    } 
    return pdog.get(); 
} 
+0

I() ' – Gili

+7

Bu cevap artık kullanılmıyor mermi ısırma ve artırmak' kullanarak :: call_once sona erdi: http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe- içinde-C11 – Yankes

2

ben size "static Dog" gibi korumasız kaynaklarla parçacığı sorunları olmayacak garanti bildiğim tek yolu hepsi herhangi ipler oluşturulur önce örneği olduğunuz bir gereklilik haline getirmek.

Bu, yalnızca başka bir şey yapmadan önce ana iş parçasında bir MyInit() işlevini çağırmak zorunda olduklarını belgelemek kadar basit olabilir. Daha sonra, bu tür istatistiklerden birini içeren her türden bir nesneyi başlatmak ve yok etmek için MyInit()'u oluşturursunuz. Diğer tek alternatif, oluşturulan kodunuzu nasıl kullanabileceklerine dair bir kısıtlama koymaktır (Boost, Win32 iş parçacığı kullanmak vb.). Bu çözümlerden her ikisi de benim görüşüme göre kabul edilebilir - takip etmeleri gereken kurallar oluşturmak iyi bir şeydir.

Belgeleriniz tarafından belirlenen kuralları izlemiyorlarsa, tüm bahisler kapalıdır. Bir başlatma işlevini çağırmaları veya Boost'a bağımlı olmaları gerektiği kuralı benim için mantıksız değildir.

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

Dog örneği ana iş parçacığı önce başlatılacaktır: iplik güvenliği için muteksi gerektirmez bunu yapabilirdi

3

bir yolu yerine statik işlevi yerine, statik Singleton bir dosya haline getirmek koşar. Dosya statik değişkenleri, başlatma emriyle meşhur bir meseleye sahiptir, fakat Köpek, başka bir çeviri biriminde tanımlanan başka herhangi bir statiğe dayanmadığı sürece, bu endişe yaratmamalıdır.

+0

Sana pencerelerde dll küresel olan başlatıcı varsa sorunlar olabileceğini hatırlamak bir DLL :) Hangi sorunlardan haberdar olmalıyım? Biliyorum eğer – olliej

+0

Kodum: ama özelliklerini hatırlamıyorum ve kod bir DLL ise yine gerçekten sadece alakalı - – Gili

+0

darned. En iyi tahminim, dll yüklendiğinde her zaman için kurucunun çalışacağıdır, böylece eğer dll yüklenmemişse ve yeniden yüklenirse, tekil "sözleşmeyi" bozar, ancak bu kadar çok şey yapamazsınız –

2

afaik, bu güvenle yapılabilir ve muteksler veya global durumlarda önceden başlatma Matthew olduğu olmaksızın olmuştur sadece zaman Wilson'un "spin mutex" kullanarak nasıl yapılacağını tartışan Imperfect C++. Kopyalarıma yakın değildim, bu yüzden size daha kesin bir şekilde anlatamam. Ben şu anda hangi bileşenleri hatırlayamıyorum ama

IIRC, STLSoft kütüphanelerin içinde bu kullanılmasının bazı örnekler vardır. Bu Şunu ya da değil, ancak bunun yerine pthread_once arayarak POSIX sistemlerinde boost bağımlılığını kaldırabilir, neyin olmadığını

4

emin değilim. Windows'da farklı bir şey yapmak zorunda olduğunu tahmin ediyorum, ancak bunun önlenmesi, desteğin ilk etapta neden bir iş parçacığı kütüphanesi olduğunu ve neden insanların buna bağlı olarak fiyatı ödeyeceklerini sormaktır. şey yapmak

"-güvenle iplik" kullanımının doğal olarak ipler uygulanması ile ilişkilidir. Sadece platforma bağlı bellek modeli olsa bile, 'a güvenmeniz gerekir. Saf C++ 03'te, dilin kapsamı dışındaki tüm konular hakkında bir şey düşünmek mümkün değildir.

İlgili konular