Użycie sekcji krytycznej w wielowątkowości

0

Cześć,
mam problem z umiejscowieniem użycia sekcji krytycznych. Mam wątek z publiczną procedurą, która zapisuje informacje do pliku, które dostarczają inne wątki. Pytanie czy uzyć sekcji krytycznej do zabezpieczenie zapisywania takiego pliku w samej procedurze zapisujacej czy w watku, ktory wywoluje taka procedure?

Przyklad:

Mam watek, ktory przy utworzeniu tworzy tez sekcje krytyczna. Procedura Zapisz, zapisuje do pliku wiadomosc przekazana przez inne procedury w tym watku (nie pokazane tutaj) jak i inne watki.

type
  TMojWatek = class(TThread)
  private
    { Private declarations }
  CS:TCriticalSection;
  public
    procedure Zapisz(msg:string);
  protected
    procedure Execute; override;
    constructor Create;
  end;


constructor TMojWatek.Create;
begin
CS.TCriticalSection.Create;
end;

I teraz pytanie czy to powinno byc zrobione w ten sposob?

procedure TMojWatek.Zapisz(msg:string);
begin
  CS.Enter;
  { TUTAJ ZAPISUJE DO PLIKU WIADOMOSC msg }
  CS.Leave;
end;

Czy zapisujac wiadomosc i wywolujac procedure gdziekolwiek robic to tak:

CS.Enter;
MojWatek.Zapisz('cos');
CS.Leave;

Prosze o pomoc:) dzieki!

1

Musiałbyś:

MojWatek.CS.Enter;
MojWatek.Zapisz('cos');
MojWatek.CS.Leave;

ponieważ musi być ten sam CS, ale chyba już widzisz bezsens.

0

@_13th_Dragon dzieki!
Bezsens w sensie CS w samej procedurze czy bezsens ogolnie takiego rozwiazania? ;)
Moglbys zaproponowac jak to rozwiazac inaczej?

0

A ja mam pytanie natury technicznej po co w ogóle tworzyć osobny wątek jeżeli jedyna rzecz jaką robi ma być w sekcji krytycznej?

0

Bo to tylko okrojona wersja. Wątek jest o wiele bardziej rozbudowany ale opisałem tylko część z którą mam problem.

Wiem już, że nie może to być tak zrealizowane jak opisałem.

Zastanawiam się tylko jak to zrobić inaczej. Pewnie nie byłoby to zbyt eleganckie rozwiązanie ale można np utworzyć globalną tablicę przechowującą sekcje krytyczne i umieszczać tam takie przy tworzeniu wątku tak aby każdy miał dostęp do każdej sekcji?

1

Po mojemu to powinno być tak, że wątki mają robić tylko swoją pracę. Tzn. jeśli wątek ma liczyć dane, to ma liczyć dane. Jeśli wątek ma rysować, to ma rysować. Wyniki, oczywiście, mogą być umieszczane w plikach, ale wątki nie powinny mieć dostępu do innych wątków (chyba, że je bezpośrednio wykorzystują). W tym momencie funkcja zapisująca komunikaty w pliku powinna być poza jakimkolwiek wątkiem. Może być składnikiem singletona albo po prostu zwykłą funkcją. I to w tej funkcji powinny być sekcje krytyczne, czyli tak, jak napisałeś. Czyli np:

var
  _cs: TCriticalSection;

function Zapisz(const msg: string): boolean;
begin
  _cs.Enter();
  //zapis
  _cs.Leave();
end;

initialization
  _cs := TCriticalSection.Create();

finalization
  if(_cs <> nil)
    FreeAndNil(_cs);

Oczywiście, ładniej by było, gdyby nikt więcej nie miał dostępu do tej sekcji krytycznej, a więc, jeśli to wszystko byłoby w jakimś singletonie.

2

@karpov - przy okazji:

TCriticalSection Class - Description napisał(a)

Critical sections must be global in scope so that they are available to all threads. In every thread, any action that could interfere with the operations safeguarded by the critical section should only take place after calling the Acquire or Enter method. Threads that do not use the critical section for relevant operations can introduce bugs.

http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/SyncObjs_TCriticalSection.html

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