2015-04-16 18 views
6

volatile ürününü m_flag tanımından kaldırmak güvenli midir? m_flag geçici değilse, derleyicilerin bu döngünün durumunu en iyi duruma getirmesini engeller: while (!m_flag) m_cv.wait(lock);? Standart (post-C++ 11) bu tür optimizasyonların bu gibi durumlarda yasak olduğunu açıkça belirtiyor mu?Burada C++ uçucusunu kaldırmak güvenli midir?

#include <mutex> 
#include <condition_variable> 
#include <future> 
#include <iostream> 
using namespace std; 

class foofoo 
{ 
    volatile bool m_flag; 
    mutex m_mutex; 
    condition_variable m_cv; 

public: 
    void DoWork() 
    { 
     m_flag = false; 
     unique_lock<mutex> lock(m_mutex); 
     auto junk = async(std::launch::async, [this]() 
     { 
      { 
       unique_lock<mutex> lock(m_mutex); 
       m_flag = true; 
      } 
      m_cv.notify_one(); 
     }); 
     while (!m_flag) m_cv.wait(lock); 
     cout << "ququ" << endl; 
    } 
}; 

int main() 
{ 
    foofoo f; 
    f.DoWork(); 
} 

cevap

10

Genel olarak, volatile ve çoklu C++ 11 ortogonaldir. volatile'u kullanarak veri yarışlarını ekler ya da kaldırmaz. Bu durumda

, m_flag = true; önce sırayla m_cv.wait(lock) içinde ile muteksin sonraki Edinme senkronize async ([intro.execution]/p14) tarafından başlatılan iplik, Muteksleri salınımını sekanslanır ([thread.mutex.requirements.mutex]/p11,25), bu da'dan önce m_flag'un bir sonraki okumasını dizilen 'dur. m_flag = true; bu nedenle arası iş parçacığı'dan önce olur ve dolayısıyla , daha sonra okunan öncesinde olur. ([Intro.multithread]/p13-14) m_flag başka hiçbir yan etkileri olduğu için

, m_flag = true; bu okuma ([intro.multithread]/p15) göre görünür yan etki olduğunu ve Bu nedenle okuma, görünür yan etki tarafından saklanan neyi okumalıdır, yani, true.

volatile'un kullanılıp kullanılmadığına bakılmaksızın bu durumu "en iyi duruma getiren" bir derleyici uyumlu olmayacaktır.

+0

Teşekkürler! Yani, başka bir deyişle, döngü gövdesi döngü koşulunu değiştirmez, ancak bir eşitleme "nokta" içeriyorsa, bir derleyicinin, döngü koşulunun "görünür bir taraftan etkilenip etkilenmeyeceğini" analiz etmesi gerekir. "aynı" nokta ile senkronize edilebilen başka bir iş parçasından "etki"? Pratikte, derleyiciler muhtemelen pes edecek ve asla bu tür döngüleri optimize etmeye çalışacaklardır? .. –

+0

"Döngünün durumunu en iyi duruma getirme" yi kastediyorum. Sadece her yerde "döngü" dediğimi fark ettim, açıkçası döngü hala kalacaktı, sadece sonsuz bir döngüye dönüştü ... –

+2

@MaxGalkin Bir veri yarışması yazmadığınız sürece derleyici değişikliklerin yapılmasını sağlamalı Daha önce bir muteks salgılayan bir iş parçacığı tarafından yapılan, daha sonra aynı muteks elde eden bir iş parçacığına görünür. "Hiç teşebbüs etme" dersem de emin değilim, ama kod veri yarışlarından arınmış olduğu sürece, uygun bir derleyici ile sürprizler olmamalı. –

1

Döngü içinde wait numaralı bir aramanız varsa, derleyicinin onu ortadan kaldırmasının bir yolu yoktur. wait'un derleyici için az ya da çok opak bir şey olabileceği gerçeğinin yanı sıra, herhangi bir elemenin derlenmesini etkin bir şekilde engelleyen mutex kilitleme/kilit açma içeriyor. Yani volatile burada tamamen işe yaramaz.

+0

Eğer m_flag yerine bu yöntemde yerel bir boole değişkeni kullanırsanız, derleyici döngü koşulunu en iyi duruma getirmek için özgür olur, çünkü yerel değişken diğer iş parçacıklarına görünmez ... "Döngünün gövdesinin içinde ... –

+1

Eğer yerelden kullandıysan muhtemelen o olurdu - Ben bir derleyici uzmanı değilim. Derleyicinin bir şeyi elimine etmesinin tek yolu (anladığım kadarıyla) değişkenin başka bir yerde değiştirilemeyeceğini kanıtlamaktır. Opak fonksiyona yapılan herhangi bir çağrı bu yeteneği muazzam bir şekilde engelleyebilir ve bir derleyici denemekten vazgeçebilir. Yine de yerel değişkeni kullandıysanız, adresini herhangi bir yerde geçmemiş olsaydınız kesinlikle başka bir yerde bulunma şansı olmazdı. – ixSci

+0

Ardından bu ifadenin cevabı yanlış: "Döngü içinde 'bekle' seçeneğiniz var, bu yüzden derleyicinin onu ortadan kaldırmasının bir yolu yok." Sadece 'bekle' çağrısına sahip olmak, elemeyi önlemek için yeterli değildir ... –

İlgili konular