PUBLIC Variabeln, DBF und Thread´s syncronisieren ?

Eigentlich ist mir die Frage peinlich, aber es kann sonst niemand helfen ... :)

Moderator: Moderatoren

Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16513
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Jimmy,
na klar! Jeder der beiden Hersteller verwendet unterschiedliche Optimierungsvarianten - insofern nicht unbedingt verwunderlich.

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Beitrag von AUGE_OHR »

hi,

das ganze bezieht sich auf eine Anfrage befreffen des Xbase++ Help Text
und der Sample zum Thema SYNC
Alaska Support hat geschrieben: > wären dann die SYNC METHOD put, get davon betroffen d.h.
> während put ausgeführt wird kann nicht get ausgeführt werden ?

Stimmt. :put() und :get() sind als synchronized deklariert. Das heisst,
dass die IVAR :nCount immer auch die Länge des Arrays :aQueue
reflektiert.

Aber vorsicht, das Beispiel hat auch eine Unschärfe, es wird in der
Funktion Test() zuerst oQ:nCount abgefragt und dann oQ:get() gerufen.
In der Zeit zwischen des IVar Zugriffs und des Methodenaufrufs kann
sich die Anzahl der Elemente natürlich verhändert haben weil ein
anderer Thread :put() gerufen hat.
eine weitere Antwort aus dem Alaska Forum
Rodd Graham hat geschrieben: Thread A - SyncVars():VarGet( 1 ) //suppose returns 10
-- context switch --
Thread B - SyncVars():VarGet( 1 ) // also returns 10
Thread B - SyncVars():VarPut( 1, 10 + 1 ) // writes 11
-- context switch --
Thread A - SyncVars():VarPut( 1, 10 + 1 ) // also writes 11
- you have lost one count

Threads are only blocked from the SYNC methods when another thread
has an active call to a SYNC method.

Put another way, the SyncVars():VarPut( cVar, SyncVars():VarGet( Var )
+ 1 ) is not executed atomically. The calls to :VarPut() and :VarGet()
are independent of one another. You just happened to code them into a
single expression. Expressions are not atomic, thread context switches
may occur in the middle of the expression evaluation
ok nachdem ich das nun begriffen hatte zusammen mit seinem Beipiel
hier nun die Zusammenfassung in meinem Code

Code: Alles auswählen

PROCEDURE Main
LOCAL i, aT[4], j
LOCAL TimeOn := SECONDS()
LOCAL TimeDiff

   CLS
   FOR i:=1 TO 4
      aT[i] := Thread():new()       // Threads erzeugen
      aT[i]:start( "Lucky4" ) // und starten
   NEXT

   ThreadWaitAll( aT )
   ? TimeDiff := SECONDS()-TimeOn

   // Den Endstand anzeigen
   FOR j:=1 TO 4
      ? SyncVars():VarGet( "Var"+LTRIM(STR(j)) )
   NEXT
   WAIT
RETURN                              // Threads beendet sind

** Code läuft in 4 Threads gleichzeitig ab
PROCEDURE Lucky4()
LOCAL i, nRow, nCol, j
LOCAL x,cString
LOCAL cThread := "T"+ltrim(str(ThreadId()))
LOCAL cVar

   nRow := 15
   nCol := (ThreadID()-2) * 10
   DispOutAt( nRow, nCol, padl( cThread, 10 ) )
   FOR i:=1 TO 1000
      FOR j := 1 TO 4
         cVar := "Var" + ltrim(str(j))
         // Anzeige var Name ...
*         DispOutAt( nRow+j, 0, cVar )
         //
         // eine dritte SYNC Methode
         //
         SyncVars():VarLock( nRow+j, nCol, cVar )
      NEXT
   NEXT

RETURN

*************************************************************
*
*
*
*************************************************************
CLASS SyncVars

PROTECTED:

CLASS VAR var1
CLASS VAR var2
CLASS VAR var3
CLASS VAR var4

EXPORTED:
// muss nun nicht mehr SYNC sein
INLINE CLASS METHOD VarPut( cVarName, value )
::&cVarName := value
return ::&cVarName

// muss nun nicht mehr SYNC sein
INLINE CLASS METHOD VarGet( cVarName )
return ::&cVarName

INLINE METHOD Init
  MsgBox("SyncVar():New() ist verboten!")
RETURN self

INLINE SYNC CLASS METHOD InitClass
  ::var1 := 0
  ::var2 := 0
  ::var3 := 0
  ::var4 := 0
RETURN self

//
// all Code will be execute before other Threads can access it
//
INLINE SYNC CLASS METHOD VarLock( nRow, nCol, cVar )
LOCAL nVar := 0

   // step by step
   //
   nVar := SyncVars():VarGet( cVar ) + 1
   //
   // just to show
   //
   SyncVars():VarPut( cVar,nVar)
   //
   // whole code will be execute by one Thread only
   //
   DispOutAt( nRow, nCol, nVar)

RETURN self

ENDCLASS
so mit diesem Code wird 100% das richtige Ergebniss erzielt d.h. die
Threads müssen richtig SYNCronisiert sein sodas sie nicht auf die
Variablen gleichzeitig zugreifen können. Somit könnte man also Variablen
,die wie PUBLIC für alle Thread gelten sollen, gegen gleichzeitigen Zugriff
z.b. beim "schreiben" wie RLOCK() bei einer DBF zum "sperren" benutzen.

Mal sehen wie das ganze dann funktioniert wenn ich das Demo in die
activeX Application einbaue und damit meine Threads SYNCronisiere.

vielen danke allen für die Hilfe, besonders Günter
gruss by OHR
Jimmy
Antworten