Dwa wątki, jedna zmienna

0

Mam klasę, która jest opakowaniem wątku. Klasa ta zawiera prywatną zmienną typu string, która jest modyfikowana jedynie w tymże wątku. Chcę aby klasa udostępniała publiczną metodę umożliwijącą pobranie tej wartości tylko do odczytu. Czy w takim wypadku musze jakoś zabezpieczyć dostęp do zmiennej?

Przykład kodu:

class Worker
{
public:
void Install() { /* start thread */ }
std::string Data() const { return data; }
private:
std::string data;
void Start()
{
while(true)
{
data = GetSomething();
}
}
}

// ...

int main()
{
   Worker w;
   w.Install();

   /* ... */
   string = w.Data();
}
1

Tak, musisz. Jednoczesny zapis z jednego wątku i odczyt z drugiego jest niebezpieczny. Jeżeli nie zmieniasz długości stringa to najprawdopodobniej w najgorszym przypadku dostaniesz śmieciowe dane, ale w/g standardu jest to UB i teoretycznie może stać się wszystko.

0

Długość stringa będzie stała, ale skoro twierdzisz że to UB to się z Tobą zogdzę :) jak najłatwiej zabiezpieczyć taką sytuację?

0

Mutex i lock_guard. Ewentualnie możesz się pobawić stringiem złożonym z atomic<char>, ale ciężko mi powiedzieć czy to by było faktycznie bezpieczne.

0

Czyli zakładam lock_guard w zmiennej która udostępnia pobranie strina oraz w zakreście w którym go modyfikuje tak ?

0

Tak. Wszędzie gdzie używasz stringa w jakikolwiek sposób opakowujesz go w lock_guarda na ten sam mutex.

0

Ok, niestety musze szukać alternatywy, MinGW pod Windowsem nie wspiera mutex'ów jeszcze :( a czy czyste WinAPI ma jakiś podobny mechanizm?

1

MinGW jak najbardziej wspiera mutexy, musisz mieć jakąś starą/wybrakowaną wersję. Jak Ci wszystko jedno to wiem, że na pewno działa wersja 4.8.2 dołączana do Qt.

Tak, WinAPI ma CriticalSection, ale jak już to bym na Twoim miejscu użył mutexów z boosta.

0

Faktycznie, najnowsza wersja C::B korzysta jeszcze z wersji 4.7

1

a czy czyste WinAPI ma jakiś podobny mechanizm?

critical sections, muteksy, semafory, są też lżejsze funkcje typu InterlockedIncrement, InterlockedDecrement i podobne.

0

A mam czy moge skorzystać z std::mutex w wątkach stworzonych przy pomocy funkcji CreateThread() z WinAPI?

0

@Azarien jak skorzystać w owych funkcji aby zachować bezpieczęństwo dostęptu do mojego stringa ?

0
KtoPytaNieBladzi napisał(a):

A mam czy moge skorzystać z std::mutex w wątkach stworzonych przy pomocy funkcji CreateThread() z WinAPI?

Tak.

0

Ok, zakładam że korzystam z critical section, wtedy kod wyglądałby mniej więcej tak:

class Worker
{
public:
     void Install() { /* start thread */ }
     std::string Data() const 
    { 
         EnterCriticalSection(&CriticalSection);
         string s = data;
         LeaveCriticalSection(&CriticalSection);
         return s; }
private:
    std::string data;
    void Start()
    {
        while(true)
        {
             EnterCriticalSection(&CriticalSection); 
             data = GetSomething();
             LeaveCriticalSection(&CriticalSection);
        }
    }
    CRITICAL_SECTION CriticalSection; 
}
 
// ...
 
int main()
{
   Worker w;
   w.Install();
 
   /* ... */
   string = w.Data();
}

I mogę spać bezpiecznie że program się nie wysypie?

0

Nie, jeszcze musisz jednorazowo (w konstruktorze) użyć InitializeCriticalSectionhttp://msdn.microsoft.com/en-us/library/windows/desktop/ms683472%28v=vs.85%29.aspx

Albo możesz użyć boost::mutex (http://www.boost.org/doc/libs/1_55_0/doc/html/thread/synchronization.html#thread.synchronization.mutex_concepts) i przejść na std::mutex jak wszystkie twoje kompilatory będą go wspierały.

1 użytkowników online, w tym zalogowanych: 0, gości: 1