Effektiv dataöverföring mellan trådar
Sitter och klurar på ett problem jag inte får någon ordning på. Jag skall så småningom implementera detta i C(pthreads) men experimenterar just nu i Java för att det är lättare.
Situationen är följande:
- Jag har två trådar, där information skall skickas från tråd 1 till tråd 2, och tråd 2 skall *väckas* när den fått informationen
- Tråd 1 pollar en extern buffert och får information därifrån.
- Tråd 2 skall reagera på när den får information från Tråd 1.
Det är inte så svårt att fixa en naiv trådsäker lösning (tror jag, gemensam synkad buffert som tråd två kopierar ifrån), MEN, jag vill hitta en lösning där jag slipper låsa (mutex lock/unlock eller semaphores) mer än ett väldigt begränsat antal gånger och som dessutom inte kräver några kopieringar.
Min tanke är att skapa 2 mellanliggande buffrar, och helt enkelt bara skifta pekare mellan dessa när det passar.
Låt oss nu säga att vi har två buffertpekare (p1 och p2) som initiellt går tilldelats buffertaddresser (a1 och a2).
p1 = a1 (initiellt)
p2 = a2 (initiellt)
Min tanke är att Tråd1 skriver fritt till p1, och tråd 2 läser fritt från p2, när tråd 2 märker att p2 är tom så går tråd 2 och lägger sig, och ev meddelar/flaggar att tråd 1 nu är tillåten att swappa adresserna som p1 och p2 lagrar.
Problemet är ju att även om tråd 1 kör swap(p1,p2) så kan kompilatorn optimerat bort att tråd 2 känner av detta pga tråd-specifik cachning. Eftersom nyckelordet "volatile" inte verkar vara generellt accepterat av alla kompilatorer och hårdvaruarkitekturer så blir jag som jag förstått det tvungen att använda pthreads egna funktioner som garanterar att båda trådarna verkligen läser från minnet och inte sin egen tråd-cache när dom skall. Men det är ju just det som är problemet.
Jag vet hur jag ska göra för att åstadkomma att pekaradress-swappen som görs av tråd 1 uppdaterar p1 och p2-adresserna hos både tråd 1 och tråd 2. MEN. Tråd 2 kan ju fortfarande ha cachat informationen som ligger i både a1 och a2, eller?
Alltså, förtydligande av problemet. Tråd två känner från början till datan som finns på adress a1 och a2. När Tråd två sedan blir tillsagd att läsa av datan på a1 och a2 igen fattar inte kompilatorn att innehållet där kan ha ändrats utan den läser bara samma gamla skräp som cachats tidigare. Eller? (obs p1 och p2 kan vara void* och innehålla data på N byte)
Every time you create an iterator: God kills a kitten.