A Sather programozási nyelv

Párhuzamosság



Ahogy már a bevezetőben említettük a Sather nyelvnek létezik egy párhuzamos és osztott programozást lehetővé tevő kiterjesztése: a pSather. Ez három párhuzamos programozási szerkezetet is biztosít, amelyek az objektum orientáltsággal (a fejlesztők szerint) ortogonálisak egymásra. Ezen három konstrukcióval már szinte minden megvalósítható.

A nyelvben a párhuzamos programozási módszerei rendkívül sokoldalúak, ezért ezeknek csak egy kis részéről lesz itt említés. Ennél jóval részletesebb dokumentáció a bevezetőben említett Sather oldalakon található.

Szinkronizálatlan szálak

Egyszerű szálakat a ‘fork’ kulcsszóval készíthetünk:

class MAIN is   main is     par       fork #OUT + "Hello World #1" + '\n' end;       fork #OUT + "Hello World #2" + '\n' end;     end;   end; end; -- class MAIN

Illetve ha sok hasonló szálat akarunk indítani, akkor a ‘parloop’ kulcsszó használata ajánlatos:

class MAIN is   main is     parloop i ::= 0.upto!(3) do@i       #OUT + ("Hello World #" + i + '\n')     end;   end; end; -- class MAIN

A @i osztott környezetben azt jelentené, hogy minden szálat külön clusteren indítson el.

Egy valós alkalmazási lehetőségként tekintsük az alábbi mátrix-szorzást (minden sort egymástól függetlenül számolunk).

class MMULT is   mult(a,b,c:MATRIX{FLT}) is     parloop x ::= b.rows.times!; do       loop y::=b.rows.times!;         loop z::=b.cols.times!;           a[y,x]:=a[y,x]+b[z,x]*c[y,z];         end;       end;     end;   end; end; --MMULT

A legegyszerűbb szinkronizációs eszköz a ‘sync’, mely hatására az egyszerre indított szálak befejezését bevárja a hívó rész. Ez a blokkoló szinkronizáció. Minden más szinkronizáció a ‘lock’ valamilyen formája. Az alap konstrukció a monitor alkalmazása, amely magas szintű eszközt biztosít olyan objektumok létrehozásához, amelyek eljárásai kölcsönös kizárás mellett futnak.

A szinkronizációk egyik alapesete a zárolás (kizárás). Ez könnyen holtponthoz vezetne, amely ellen csak valami alapszintű védelem van beépítve a nyelvbe, biztos nincsen. Zárolást a $LOCK osztály példányosításával konkretizálhatunk, aminek példányosításával zárokat készíthetünk, melyeket a ‘lock’ kulcsszóval aktiválhatunk (és hatása ‘end’-ig tart). Például:

if big > m then   lock big_lk then     big := big.max(m)   end end;

Kapuk

A ‘GATE’ és a ‘GATE{T}’ osztályok a pSather legösszetettebb és leghatékonyabb eszközei. A GATE osztály korábban monitor volt, de aztán annál egy általánosabb és sokkal hatásosabb eszköz lett. A feladata hasonlóan adatok elrejtése kapuk mögé, de itt már nem csak egy eljárás futhat egy időben, mivel olvasni nyugodtan lehetne több szálon is egyszerre. De ekkor külön jelölni kell azokat az eljárásokat, amelyek csak kizárólagosan futhatnak (amik módosítanak). Tehát ez az eszköz lehetőséget biztosít az ismert író-olvasó probléma magas szintű megvalósítására.

Taszkok

Párhuzamos programozás egy további népszerű eszköze az üzenetküldés. Satheben erre is van lehetőség, a $TASK típusból származtatott osztályok segítségével, amelyek taszkokat implementálnak. Kommunikációt PORT objektumokon keresztül végezhetnek:. Például:

abstract class $TASK is   connect(sender:$TASK);   outport: PORT{STR};   body; end; -- class $TASK   partial class TASK > $TASK is   attr inport,outport: PORT{STR};   private shared all:GATE;          -- ezen típusba tartozó összes taszk     create:SAME is     res ::= new;     res.inport := #;     res.outport := #;     return res   end; -- create     start:SAME is     if void(all) then all := # end;     all:-body;     return self   end;     stub body;     send(datum:STR) is     outport.send(datum)   end; -- send     receive:STR is                    -- blokkolódik, amíg nincs adat     return inport.receive   end; -- receive     connect(sender:$TASK) is          -- használat: receiver.connect(sender)     sender.outport.channel := inport.channel   end; end; -- class TASK