[C] threads die memory sharen

Pagina: 1
Acties:

  • Zynth
  • Registratie: September 2001
  • Laatst online: 29-07 15:30
Ik wil in mijn programma een "globale" variabele,
waar alle threads gebruik van kunnen maken.
Als ik bijvoorbeeld de ene thread eerst die variabele op 3
laat zetten, moet dat in een andere thread ook 3 worden.

een beetje volgens dit idee:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int i;
  
  
  if(fork()>0){
    //het ene kind gaat nu steeds i++ doen
    while(1){
      i++;
      sleep(1);
    }
  }
  
  if(fork()>0){
    //het andere kind gaat i printen.
    //omdat ik wil dat i een gedeelde variabele is,
    //zou in deze printf i dus ook moeten veranderen.
    while(1){
      printf("%d\n",i);
      sleep(1);
    }
  }
     sleep(100);
     exit(0);
}


Ik heb al gegoogled maar omdat ik geen C-guru ben
kom ik er niet uit...
Ik weet dat het niet standaard met fork() kan, omdat fork
een copy-on-write memory strategie heeft. Maar wat
zou dan in dit geval wel handig zijn?

  • Rukapul
  • Registratie: Februari 2000
  • Laatst online: 00:08
Kijk eens naar een thread library, bijvoorbeeld pthreads. Ipv fork() gebruik je dan een functie die een thread maakt.

Om een variable te delen is het overigens verstandig zo'n variabele te beschermen met mutexen, semaforen, etc. welke je ook door de thread library aangeboden worden :)

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 22:29

johnwoo

3S-GTE

- Threads delen sowieso al geheugen, ze draaien namelijk in hetzelfde proces ;)
- In je voorbeeldje gebruik je geen meerdere threads maar meerdere processen. In het geval van processen zul je inderdaad speciale maatregelen moeten treffen als je (gedeelten van) hun geheugenruimtes wilt delen. Het delen van geheugen tussen processen gebeurt via platform-specifieke methoden.
- Een thread maak je in ansi C met beginthread().
- Zowel bij threads als bij processen zul je synchronisatie moeten toepassen, bijvoorbeeld met mutexen of semaforen. Jouw twee lusjes zijn niet gesynchroniseerd, dus er kan niet gegarandeerd worden dat je in je tweede lus 1,2,3,4,... te zien krijgt.
- Declareer variabelen die door meerdere threads (of processen) aangesproken zullen worden altijd volatile. Daarmee vertel je de compiler dat de waarde van de variabele bij wijziging altijd direct naar het geheugen geschreven dient te worden, en niet gecached in een register.

Voorbeeldje met simpele synchronisatie:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <process.h>
#include <stdio.h>

#ifdef WIN32
#include <windows.h>
#define beginthread _beginthread
#define sleep(sec) Sleep((sec)*1000)
#endif

void mythreadfunction(void *dummy);
volatile int variable;
volatile int mutex;

int main() {
    int counter;
    variable = 0;
    mutex = 1;

    if (beginthread(mythreadfunction, 0, NULL) == -1) {
        printf("Oeps, kan de thread niet fixen :o\n");
        return 1;
    }

    for (counter = 0; counter < 10; counter++) {
        while (mutex == 1) ;
        variable = counter;
        mutex = 1;
        sleep(1);
    }
    
    return 0;
}

void mythreadfunction(void *dummy) {
    while (variable < 10) {
        mutex = 0;
        while (mutex == 0) ;
        printf("variable = %d\n", variable);
    }
}

De mythreadfunction zal gegarandeerd altijd de getallen 0 t/m 9 printen, omdat toegang tot de variabele geregeld wordt via mutex (in dit geval is de mutex een flag, maar er zijn ook tellende semaforen die toegang voor meer dan 1 schrijvende thread kunnen regelen).
Dit programma zal 100% CPU trekken omdat er steeds in een while lusje gewacht wordt op de mutex. Maak daarom bij voorkeur gebruik van de faciliteiten die je OS levert, die gebruiken een kernel wait, waardoor je CPU usage niet omhoog zal schieten terwijl je thread op z'n beurt wacht ;)

[ Voor 73% gewijzigd door johnwoo op 22-06-2003 21:52 ]

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


  • Zynth
  • Registratie: September 2001
  • Laatst online: 29-07 15:30
hmm... als dat ook in linux/unix werkt dan is dat wel ideaal inderdaad.
Omdat ik C ken (er gaan altijd de meest rare/vage/irritante dingen fout :))
zal ik toch even uitleggen wat uiteindelijk het doel is.
in mijn programma zoals het nu is, maak ik een serversocket aan.
Voor elke client die daarop connect, start ik met fork() een nieuwe instantie,
die die client afhandeld. het probleem was, dat alle clients toegang (rw) moeten
hebben tot een centrale variabele die iets bijhoud wat alle clients moeten weten.
Kan dat op de manier van de vorige post, ook gewoon in deze opzet zo blijven?

  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 19-08 15:46
misschien wat off topic, maar als ik in C onder linux threads gebruik, dan doe ik dit alitjd via de functie pthread_create

is hier een verschil met beginthread ? of wanneer wordt wat dan juist gebruikt ?

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 22:29

johnwoo

3S-GTE

Cuball schreef op 22 June 2003 @ 22:36:
misschien wat off topic, maar als ik in C onder linux threads gebruik, dan doe ik dit alitjd via de functie pthread_create

is hier een verschil met beginthread ? of wanneer wordt wat dan juist gebruikt ?
Ik ben geen linux coder, maar ik denk dat pthread_create linux (of iig *nix) specific is, net zoals CreateThread Win32 specific is, terwijl beginthread ansi C is.

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
De p in pthread_create staat voor POSIX en is dan ook een functie die voorgeschreven wordt door de POSIX standaard. Dat 'standaard' moet je met een korreltje zout nemen, want Windows doet er helemaal niet aan, en andere systemen zoals bijvoorbeld BSD hebben vaak net wat ander gedrag dan bijvoorbeeld Linux (en ik moet zeggen dat ik niet zou weten wat nu eigenlijk het 'goede' gedrag is).

Al met al is gebruik van de pthread functies een stuk beter portable dan het gebruik van een Linux of Windows thread functie (die echt alleen maar onder Linux of Windows werkt). Verwacht echter niet dat daarmee je code direct 100% portable is; daarvoor zal je op de verschillende platformen moeten testen en zonodig je code aanpassen. Reken er bovendien niet op dat het op Windows werkt (of ooit gaat werken, al zijn er wel projects die dat proberen te bereiken). Als je portabiliteit naar de meeste moderne besturingssystemen, zul je minimaal zowel Windows als POSIX threading moeten implementeren, maar dan heb je ook wel praktisch alle relevante platforms.

edit:
Mijn FreeBSD installatie heeft geen man-page over beginthread, dus hij is zeker geen onderdeel van de standaard C library. Misschien is dat juist wel wat platformspecifieks. Heb je 'm niet toevallig zelf verzonnen? ;)

[ Voor 12% gewijzigd door Soultaker op 22-06-2003 23:23 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
beginthread is helemaal geen ansi C. ANSI C (eigenlijk ISO C) heeft helemaal geen threads.

C++ proggers kunnen boost threads gebruiken, die zijn weliswaar nog experimenteel maar wel Win32/POSIX compatible, en zitten vrijwel zeker in de volgende ISO C++

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

beginthread roept gewoon CreateThread aan onder windows. Er is een rede dat je juist beginthread wil gebruiken ipv CreateThread. Zie MSDN.

  • Zynth
  • Registratie: September 2001
  • Laatst online: 29-07 15:30
ik denk dat ik dan maar gewoon pthread_create() gebruik met een pthread_mutex_t.
Should do the trick :)

  • Zynth
  • Registratie: September 2001
  • Laatst online: 29-07 15:30
ik bedenk me net dat ik wel een probleempje heb zo.
Er kunnen namelijk een willekeurig X aantal clients tegelijk connecten
met mijn programma, waardoor ik X threads nodig heb. Bij het starten van het
programma wordt aangegeven hoeveel clients maximaal kunnen connecten (bijvoorbeeld Y).
Hoe kan ik nou op deze manier Y pthread_t's declaren?

[ Voor 4% gewijzigd door Zynth op 23-06-2003 15:43 ]


Verwijderd

C:
1
2
3
4
5
6
for (i = 0; i < argv[1];i++)
  if (beginthread(mythreadfunction, 0, NULL) == -1) 
  { 
    printf("Oeps, kan de thread niet fixen :o\n"); 
    return 1; 
  } 


Op deze manier worden er afhankelijk van het 1e argument na de programma aanroep ("bla.exe 5) dat aantal threads aangemaakt. Wil je ze echter later ook nog aan kunnen spreken, dan zul je een manier moeten verzinnen om ze een dynamische naam te geven. Tevens moet je het argv[1] argument van te voren nog converteren naar een int (zoek s op de atoi functie).

[ Voor 15% gewijzigd door Verwijderd op 23-06-2003 22:07 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Verwijderd schreef op 23 June 2003 @ 00:27:
beginthread roept gewoon CreateThread aan onder windows. Er is een rede dat je juist beginthread wil gebruiken ipv CreateThread. Zie MSDN.
_beginthread (met underscore) dien je te gebruiken om memory leaks te voorkomen als je de C standard libs gebruikt (hoef ik MSDN niet voor open te slaan ;) )

Professionele website nodig?


Verwijderd

curry684 schreef op 23 June 2003 @ 22:07:
[...]

_beginthread (met underscore) dien je te gebruiken om memory leaks te voorkomen als je de C standard libs gebruikt (hoef ik MSDN niet voor open te slaan ;) )
Maar jij bent dan ook een windows hippie.. :+

  • Zynth
  • Registratie: September 2001
  • Laatst online: 29-07 15:30
maareh, uit de post van tazboy begrijp ik dus dat het creeren van een thread niet persé hoeft te worden opgeslagen?
als in:
normaal doe je:
pthread_t thread;
pthread_create(&thread,blablabla);

dat je dan als je 3 threads wil (zonder ze te hoeven aanspreken)
je ook kan doen:
pthread_t thread;
pthread_create(&thread,blablabla);
pthread_create(&thread,blablabla);
pthread_create(&thread,blablabla);

??
of mol je dan je eerste en tweede thread :P

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Nee, dan overschrijf je alleen het resultaat van pthread_create, wat in veel gevallen geen enkel probleem is. Je threads vinden dit allemaal prima.
Pagina: 1