Wielowątkowość - problem z synchronizacją

0

Chciałbym zsynchronizować dwie klasy, które posiadają wskaźnik na ten sam zasób.

  1. Czy mój kod jest poprawny?
  2. Czemu po zmianie join na detach program nie działa?
  3. Czemu po dodaniu mutexa(skomentowany w kodzie) program się nie kompiluje?
class Foo
{
private:
	bool free = true;
public:
	bool isFree()
	{
		return free;
	}
	void setFree(bool free)
	{
		this->free = free;
	}
};
class Owner
{
private:
	std::shared_ptr<Foo> ptr;
	//std::mutex mtx;
public:
	Owner(std::shared_ptr<Foo> ptr) : ptr(ptr)
	{
	}
	void run()
	{
		while (true)
		{
			//mtx.lock();
			if (ptr->isFree())
			{
				ptr->setFree(false);
				std::cout << "GIT\n";
				Sleep(1000);
				ptr->setFree(true);
			}
			//mtx.unlock();
		}
	}
};
int main()
{
	Foo foo;
	Owner o1 = Owner(std::make_shared<Foo>(foo));
	Owner o2 = Owner(std::make_shared<Foo>(foo));
	std::thread t1(&Owner::run, &o1);
	std::thread t2(&Owner::run, &o2);
	t1.join();
	t2.join();
}

3
Cepo napisał(a):
  1. Czy mój kod jest poprawny?
  2. Czemu po zmianie join na detach program nie działa?
  3. Czemu po dodaniu mutexa(skomentowany w kodzie) program się nie kompiluje?

Ad. 1: Nie, zamiast:

	Foo foo;
 	Owner o1 = Owner(std::make_shared<Foo>(foo));
 	Owner o2 = Owner(std::make_shared<Foo>(foo));

powinno być:

	auto ptr = std::make_shared<Foo>();
	Owner o1 = Owner(ptr);
	Owner o2 = Owner(ptr);

Ad. 2: Ponieważ program natychmiast opuszcza funkcję main i cały proces łącznie z uruchomionymi zadaniami jest zamykany.

PS.
Zamiast Sleep, używaj std::sleep_for

PS.2
W Twoim programie mutex niczego nie synchronizuje.

3

Biorąc pod uwagę, że

  • wątki nie współdzielą zasobów, a tego oczekujesz
  • kod wygląda chaotycznie
  • tu nie ma co synchronizować

To powinieneś się skupić na opanowaniu zwykłego programowania, zamiast się brać za programowanie wielowątkowe.
Programowanie wielowątkowe jest

  • trudne
  • łatwo popełnia się błędy, których nie widać (program działa w 1000 przypadków, a w 1001 będzie crashował/dawał złe wyniki).
  • wymaga dużej dyscypliny
  • wymaga dobrej znajomości narzędzi

Ergo, najpierw trzeba opanować podstawy i więcej, zanim zacznie się bawić w wielowątkowość.
Próbując na siłę, w najlepszym razie zniechęcisz się porażkami, w najgorszym dojdziesz coś ci zadziała przez przypadek i dojdziesz do fałszywego przekonanie, że się czegoś nauczyłeś.

Cepo napisał(a):

Chciałbym zsynchronizować dwie klasy, które posiadają wskaźnik na ten sam zasób.

  1. Czy mój kod jest poprawny?

NIE.

  1. Czemu po zmianie join na detach program nie działa?

Zdefiniuj "nie działa"

  1. Czemu po dodaniu mutexa(skomentowany w kodzie) program się nie kompiluje?

Brak inculde? Podaj pełny kod, który się skompiluje bez dopisywania (domyślania się) czegokolwiek.

2

Do wypowiedzi Marka dodam jeszcze od siebie: nawet jeśli potrzebujesz wykorzystać wiele wątków, to bardzo rzadko/nigdy nie będziesz używać niskopoziomowych narzędzi takich jak mutex czy thread. Jest pełno bibliotek i frameworków do tego, gdzie jedynie określasz ile ma być wątków wykonania i przekazujesz funkcje/obiekty do threadpoola albo czegoś zbliżonego.

Zgadzam się, że trzeba tu zacząć od podstaw programowania.

Ponadto jeszcze jedna istotna sprawa, która sprawia problemy nowicjuszom: wielowątkowość i współbieżność to różne terminy, tylko częściowo się pokrywające znaczeniowo. Jeśli program ma wykonywać kilka akcji "na raz" - np. czytać z socketa i obsługiwać UI to prawie na pewno użycie wielowątkowości jest tu błędem.

3

Ja jeszcze dodam, że jeśli naprawdę chcesz efektywnie spożytkować czas, to naucz się pisać testy do kodu.
Używając gtest lub catch2.
Jako początkującemu będzie ci się to wydawać dziwne i mniej "sexy" niż wielowątkowość, ale podstawowe funkcjonalności łatwe w opanowaniu, a jest to umiejętność dużo ważniejsza niż programowanie wielowątkowe.

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