Bunu duyduğuma const
araçlar parçacığı güvenli içinde 11 C ++ . Bu doğru mu?
Öyle biraz gerçek ...
Standart Dil'in iş parçacığı güvenliği konusunda söylediği şey bu :
[1.10 / 4]
İki sentezleme değerlendirmeleri çakışma bunlardan biri bir bellek konumu (1.7) diğeri de veya bu değiştirir aynı bellek yeri değiştirmesi durumunda.
[1.10 / 21]
Bir programın yürütülmesi,farklı iş parçacıklarında en az biri atomik olmayan ve ikisi de diğerinden önce gerçekleşmeyen iki çakışan eylemiçeriyorsa bir veri yarışı içerir. Bu tür herhangi bir veri yarışı, tanımlanmamış davranışla sonuçlanır.
Bu, bir veri yarışının gerçekleşmesi için yeterli koşuldan başka bir şey değildir :
- Belirli bir şey üzerinde aynı anda gerçekleştirilen iki veya daha fazla eylem vardır; ve
- Bunlardan en az biri bir yazı.
Standart Kütüphanesi biraz daha gidiyor, o üzerine inşa:
[17.6.5.9/1]
Bu bölüm, uygulamaların veri yarışlarını (1.10) önlemek için karşılaması gereken gereksinimleri belirtir. Her standart kitaplık işlevi, aksi belirtilmedikçe her bir gereksinimi karşılamalıdır. Uygulamalar, aşağıda belirtilenler dışındaki durumlarda veri yarışlarını engelleyebilir.
[17.6.5.9/3]
Bir C ++ standart kitaplık işlevi, nesnelere doğrudan veya dolaylı olarak işlevin const olmayanargümanlarıaracılığıyla erişilmediği sürece, geçerli evre dışındaki evreler tarafından erişilebilen nesneleri (1.10) doğrudan veya dolaylı olarak değiştirmemelidirthis
.
basit bir deyişle, const
nesneler üzerindeki işlemlerin iş parçacığı açısından güvenli olmasını beklediğini söylüyor . Bu, Standart Kitaplığınconst
kendi türlerinizdeki nesneler üzerinde işlemler yapılmadığı sürece bir veri yarışı getirmeyeceği anlamına gelir.
- Tamamen okumalardan oluşur - yani hiçbir yazı yoktur -; veya
- Yazmaları dahili olarak senkronize eder.
Bu beklenti türlerinizden biri için geçerli değilse, Standart Kitaplığın herhangi bir bileşeni ile doğrudan veya dolaylı olarak kullanılması bir veri yarışına neden olabilir . Sonuç olarak, Standart Kitaplık açısından iş parçacığı açısından güvenliconst
anlamına gelir . Bunun sadece bir sözleşme olduğunu ve derleyici tarafından uygulanmayacağını unutmamak önemlidir , eğer onu bozarsanız tanımsız davranışlarla karşılaşırsınız ve kendi başınıza olursunuz. Mevcut olup olmaması, kod üretimini etkilemeyecektir - en azından veri yarışları açısından -.const
Demek oluyor mu const
eşdeğer şimdi olduğu Java'nın 's synchronized
?
Hayır . Bir şey değil...
Bir dikdörtgeni temsil eden aşağıdaki aşırı basitleştirilmiş sınıfı düşünün:
class rect {
int width = 0, height = 0;
public:
/*...*/
void set_size( int new_width, int new_height ) {
width = new_width;
height = new_height;
}
int area() const {
return width * height;
}
};
Üye fonksiyonlu area
olan iş parçacığı güvenli ; değil çünkü const
tamamen okuma işlemlerinden oluşuyor. Hiçbir yazma işlemi yoktur ve bir veri yarışının gerçekleşmesi için en az bir yazma işlemi gereklidir . Bu, istediğiniz kadar konu başlığından arayabileceğiniz area
ve her zaman doğru sonuçlar alacağınız anlamına gelir .
Bunun iş parçacığı için güvenlirect
olduğu anlamına gelmediğini unutmayın . Aslında, onun kolay bir çağrı olmadığını görmek için vardı yapılan bir çağrı aynı anda gerçekleşmesi belirli bir üzerine , daha sonra (bozuk değerler üzerinde bile ya) eski bir genişlik ve yeni bir yüksekliğe dayalı olarak sonucun hesaplanması bitebileceğini .area
set_size
rect
area
Ancak rect
sorun değil , sonuçta iş parçacığı için güvenliconst
olması beklenmiyor . Öte yandan bildirilen bir nesne , hiçbir yazma mümkün olmadığından iş parçacığı açısından güvenli olacaktır (ve eğer orijinal olarak bildirilmiş bir şeyi düşünüyorsanız , o zaman tanımsız davranış elde edersiniz ve işte budur).const rect
const_cast
const
Öyleyse bu ne anlama geliyor?
Varsayalım ki - argüman uğruna - çarpma işlemlerinin son derece maliyetli olduğunu ve mümkün olduğunda onlardan kaçınmamız daha iyi olur. Alanı yalnızca talep edilirse hesaplayabilir ve daha sonra tekrar talep edilmesi durumunda önbelleğe alabiliriz:
class rect {
int width = 0, height = 0;
mutable int cached_area = 0;
mutable bool cached_area_valid = true;
public:
/*...*/
void set_size( int new_width, int new_height ) {
cached_area_valid = ( width == new_width && height == new_height );
width = new_width;
height = new_height;
}
int area() const {
if( !cached_area_valid ) {
cached_area = width;
cached_area *= height;
cached_area_valid = true;
}
return cached_area;
}
};
[Bu örnek, çok yapay görünüyorsa, zihinsel yerini alabilecek int
bir tarafından çok büyük dinamik olarak ayrılan tamsayı doğal olmayan bir iş parçacığı güvenli ve kendisi için çarpımları son derece masraflıdır.]
Üye işlev area
artık evreli artık yazma yapıyor ve içten senkronize edilmez. Sorun mu? Çağrısı area
bir parçası olarak ortaya çıkabilir kopyalamaya karşı yapıcı bir başka nesnenin, bu tür yapıcı bir bazı operasyonla denilen olabilirdi standart konteyner , ve bu noktada standart kütüphane bu işlem bir şekilde davranmasını bekler okuma konusunda veri yarışları . Ama yazılar yazıyoruz!
Doğrudan veya dolaylı olarak standart bir konteynererect
bir tane koyar koymaz , Standart Kitaplık ile bir sözleşme yapıyoruz . Bu sözleşmeyi yerine getirirken bir işlevde yazmaya devam etmek için, bu yazıları dahili olarak senkronize etmemiz gerekir:const
class rect {
int width = 0, height = 0;
mutable std::mutex cache_mutex;
mutable int cached_area = 0;
mutable bool cached_area_valid = true;
public:
/*...*/
void set_size( int new_width, int new_height ) {
if( new_width != width || new_height != height )
{
std::lock_guard< std::mutex > guard( cache_mutex );
cached_area_valid = false;
}
width = new_width;
height = new_height;
}
int area() const {
std::lock_guard< std::mutex > guard( cache_mutex );
if( !cached_area_valid ) {
cached_area = width;
cached_area *= height;
cached_area_valid = true;
}
return cached_area;
}
};
area
Fonksiyonu iş parçacığı için güvenli yaptığımıza dikkat edin , ancak rect
yine de iş parçacığı için güvenli değildir . Bir çağrı area
çağrı için aynı anda oluyor set_size
hala atamaları beri, yanlış değer hesaplayan sona erebilir width
ve height
Muteksleri tarafından korunmaz.
Eğer gerçekten bir iş parçacığı güvenli isteseydik, iş parçacığı güvenli olmayanlarırect
korumak için bir senkronizasyon ilkelini kullanırdık . rect
Onlar tükeniyor anahtar kelimeler ?
Evet onlar. İlk günden beri anahtar kelimeleri tükeniyor .
Kaynak : Bilmiyorsunuz const
vemutable
- Herb Sutter