Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TInterlocked.Exchange bei Zugriff eines nur lesenden Threads? (https://www.delphipraxis.net/184301-tinterlocked-exchange-bei-zugriff-eines-nur-lesenden-threads.html)

Zacherl 16. Mär 2015 13:43

Delphi-Version: XE7

TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
Hallo zusammen,

ich habe zwei Threads die beide auf gemeinsame Felder zugreifen. Der eine Thread kann jeweils nur schreiben, der andere nur lesen. Muss ich nun alle schreibenden Zugriffe z.b. per TInterlocked.Exchange absichern oder ist das bei nur lesendem Zugriff des einen Threads nicht nötig?

Kann es überhaupt passieren, dass die CPU Datentypen wie Byte, Word, DWord nicht atomar schreibt?

Viele Grüße
Zacherl

himitsu 16. Mär 2015 14:14

AW: TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
Diese Interlocked-Funktionen arbeiten "atomar", so daß beim Schreibzugriff kein anderer Lesen kann.

Falls die CPU es nicht absichert, daß ein anderer Thread gleichzeitig liest, während ein Anderer schreibt, dan könnte es vielleicht passieren, daß zu von den 4 Bytes eines DWORD/INT teilweises noch ein paar Bytes von dem alten wert mit ausliest. :gruebel:

Sir Rufo 16. Mär 2015 14:32

AW: TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
Der Speicher wird immer in Busbreite ausgelesen/geschreiben. Einen zusammengestückelten Wert wie 2 Bytes vom alten und 2 Bytes vom neuen Wert gibt es nicht.

Wenn du also absolut schreibst (kein addieren) dann kannst du den Wert einfach dort hineinschreiben. Sobald du mehr als einen Zugriff machen musst, um das gewünschte Resultat zu erreichen, musst du den Bereich schützen.

Zacherl 16. Mär 2015 14:42

AW: TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1293655)
Der Speicher wird immer in Busbreite ausgelesen/geschreiben. Einen zusammengestückelten Wert wie 2 Bytes vom alten und 2 Bytes vom neuen Wert gibt es nicht.

Gut, dann bin ich vorerst beruhigt :stupid:

Zitat:

Zitat von Sir Rufo (Beitrag 1293655)
Wenn du also absolut schreibst (kein addieren) dann kannst du den Wert einfach dort hineinschreiben. Sobald du mehr als einen Zugriff machen musst, um das gewünschte Resultat zu erreichen, musst du den Bereich schützen.

Jap, sowas sichere ich in der Regel mit Critical Sections.

Bei zwei Threads die beide schreiben, muss ich doch theoretisch sogar auch nichts absichern, sofern der neue Wert nicht vom alten Wert abhängt oder?

Sir Rufo 16. Mär 2015 15:09

AW: TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
Zitat:

Zitat von Zacherl (Beitrag 1293661)
Bei zwei Threads die beide schreiben, muss ich doch theoretisch sogar auch nichts absichern, sofern der neue Wert nicht vom alten Wert abhängt oder?

Schreib dir einfach einen Thread, der immer wieder in eine "globale" Variable einen zufälligen Wert schreibt.

Schreibe einen weiteren, der aus dieser Variable liest.

Starte jetzt mehrere von beiden Threads und schau, ob da etwas knallt. Dann hat man auch einen Erfahrungswert und wird noch viel ruhiger :)

himitsu 16. Mär 2015 15:57

AW: TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
In Richtung Multiplatform betrachtet ... benutzte einfach die neuen Interlocked-Funktionen aus der System-Unit.

Die aus der Windows-Unit kann man bekanntlich nicht überall benutzen.
Aus irgendeinem unerfindlichem Grunde mach der Mac die WinAPIs nicht. :stupid:

Der schöne Günther 16. Mär 2015 16:41

AW: TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1293655)
Einen zusammengestückelten Wert wie 2 Bytes vom alten und 2 Bytes vom neuen Wert gibt es nicht.

Ausnahme wo einfaches Lesen/Schreiben auch mit "simplen" Typen wie Integer knallt ist in wenn dieser in einem
Delphi-Quellcode:
packed record
steckt.

Außerdem willst du eines Tages vielleicht doch mit mehreren Threads den Wert beschreiben und freust dich dann dass es direkt ohne Anlauf möglich ist. Ich würde einfach
Delphi-Quellcode:
TInterLocked
oder sonst was verwenden und glücklich sein.

Sir Rufo 16. Mär 2015 16:46

AW: TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1293674)
Zitat:

Zitat von Sir Rufo (Beitrag 1293655)
Einen zusammengestückelten Wert wie 2 Bytes vom alten und 2 Bytes vom neuen Wert gibt es nicht.

Ausnahme wo einfaches Lesen/Schreiben auch mit "simplen" Typen wie Integer knallt ist in wenn dieser in einem
Delphi-Quellcode:
packed record
steckt.

Das habe ich doch auch implizit erläutert ...

Zacherl 16. Mär 2015 18:43

AW: TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1293674)
Außerdem willst du eines Tages vielleicht doch mit mehreren Threads den Wert beschreiben und freust dich dann dass es direkt ohne Anlauf möglich ist. Ich würde einfach
Delphi-Quellcode:
TInterLocked
oder sonst was verwenden und glücklich sein.

Nene die Felder sind in normalen Klassen. Fehlt bei den Interlocked Implementationen von Delphi btw. die 16 Bit Variante oder bin ich blind?

Zu den packed records. Sowas würde also nicht funktionieren? Verstehe ich jetzt nicht ganz .. :shock:
Delphi-Quellcode:
type
  TRec = packed record
    A: Integer;
  end;

..

Rec.A := 100;
Außer des Alignments (was beim ersten Element hier in dem Beispiel natürlich egal wäre), ändert das "packed" Attribut doch eigentlich nichts an der ganzen Geschichte.

Uwe Raabe 16. Mär 2015 20:59

AW: TInterlocked.Exchange bei Zugriff eines nur lesenden Threads?
 
Zitat:

Zitat von Zacherl (Beitrag 1293694)
Zu den packed records. Sowas würde also nicht funktionieren? Verstehe ich jetzt nicht ganz .. :shock:
Delphi-Quellcode:
type
  TRec = packed record
    A: Integer;
  end;

..

Rec.A := 100;
Außer des Alignments (was beim ersten Element hier in dem Beispiel natürlich egal wäre), ändert das "packed" Attribut doch eigentlich nichts an der ganzen Geschichte.

So wohl nicht, aber das hier:

Delphi-Quellcode:
type
  TRec = packed record
    B: Byte;
    A: Integer;
  end;
führt dazu, daß A eher nicht auf einer der CPU genehmen Speichergrenze liegt und die damit zwei Zyklen zum Schreiben braucht. Zwischen diesen beiden Zyklen kann aber ein Lesezugriff (ebenfalls zwei Zyklen) erfolgen. Das hängt aber auch konkret von der verwendeten CPU ab.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:20 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz