|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Apr 2007
Messaggi: 51
|
[C] soluzione al problema lettori/scrittori con mutex e variabili condizionali
Ciao a tutti, devo scrivere codice C che usando mutex e variabli condizionali, mi porti a risolvere il problema dei lettori/scrittori....
Qualcuno saprebbe indicarmi dove reperire delle informazioni du questo classico problema di sincronizzazione di processi concorrenti? Sto cercando ma ancora non ho trovato niente che non usi i semafori..... Grazie |
|
|
|
|
|
#2 |
|
Member
Iscritto dal: Apr 2007
Messaggi: 51
|
Nessuno sa indicarmi anche solo la spiegazione del problema?
possibilmente in italiano? il problema "lettori-scrittori" con precedenza agli scrittori dovrebbe essere conosciuto, tutti ne parlano come di un classico problema di sincronizzazione, ma nessuno scrive di più o spiega come funziona.... o almeno io non l'ho trovato! Nessuno ne sa niente? Aiutatemi, per favore.... Grazie |
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Mar 2002
Città: Provincia di Varese
Messaggi: 5096
|
Quote:
Di link su google se imposti "mutex read write" ne trovi diversi, adesso non te ne linko uno perché non mi piacerebbe indicartene uno sostanzialmente a caso. Se hai bisogno di qualche info in più contattami pure! |
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
E' un classico problema di passaggio del testimone.
Dopo che uno qualsiasi dei thread di lettura e scrittura ha terminato la sua operazione, fai in modo che controlli se c'è almeno uno scrittore bloccato in attesa su una mutex (una condition in realtà) venga risvegliato uno di questi scrittori. Inoltre, se non ci sono scrittori in attesa, ma ci sono sono lettori in attesa si sveglia un lettore. E' importante in questi casi che un thread risvegli solamente un altro thread, di fatto gestisci in questo modo la mutua esclusione. E' chiaro che ci sarà starvation per i lettori. |
|
|
|
|
|
#5 |
|
Member
Iscritto dal: Sep 2005
Messaggi: 82
|
non è passato molto tempo da quando anche io mi sono interessato alla questione
se ti può servire, ecco un listato del problema produttore-consumatore (altro modo per chiamare scrittore-lettore). fa uso di un monitor con un mutex e due variabili condizionali essenzialmente il processo fa partire due thread (oltre al main), chiamati rispettivamente produttore (scrittore) e consumatore (lettore). entrambi devono accedere ad una stessa area di memoria (il così chiamato buffer di dimensione 16) protetto da un mutex per garantire la mutua esclusione. il senso del giovo è garantire la corretta interazione tra chi riempie il buffer (il produttore) e chi lo consuma impedendo comportamenti scorretti quali la lettura di un buffer vuoto e l'inserimento in un buffer pieno. nelle situazioni intermedie invece entrano in gioco le variabili condizionali che permettono il risveglio di determinati thread in attesa di un certo evento. ad esempio quando il buffer è vuoto il lettore non può ovviamente leggere il contenuto e si mette quindi in attesa che lo scrittore compia l'operazione di inserimento. Codice:
#include <stdio.h>
#include <pthread.h>
#define OVER -1
#define max 100
#define BUFFER_SIZE 16
typedef struct {
int buffer[BUFFER_SIZE];
pthread_mutex_t lock;
int readpos, writepos;
int buffer_count;
pthread_cond_t buffer_empty;
pthread_cond_t buffer_full;
} prodcons;
prodcons buffer;
int go;
/* Inizializza il buffer */
void init(prodcons *b) {
pthread_mutex_init (&b->lock, NULL);
pthread_cond_init (&b->buffer_empty, NULL);
pthread_cond_init (&b->buffer_full, NULL);
b->buffer_count=0;
b->readpos = 0;
b->writepos = 0;
}
/* Inserimento: */
void inserisci(prodcons *b, int data) {
pthread_mutex_lock (&b->lock);
/* mentre il buffer è pieno sospendo l'inserimento */
while(b->buffer_count==BUFFER_SIZE)
pthread_cond_wait (&b->buffer_full, &b->lock);
/* scrivi data e aggiorna lo stato del buffer */
b->buffer[b->writepos] = data;
b->buffer_count++;
b->writepos++;
if(b->writepos >= BUFFER_SIZE)
b->writepos = 0;
/* risveglia eventuali thread (consumatori) sospesi all'empty */
pthread_cond_signal(&b->buffer_empty);
pthread_mutex_unlock(&b->lock);
}
/*ESTRAZIONE: */
int estrai(prodcons *b) {
int data;
pthread_mutex_lock (&b->lock);
/* mentre il buffer è vuoto sospendo l'estrazione */
while(b->buffer_count==0)
pthread_cond_wait (&b->buffer_empty, &b->lock);
/* leggi data e aggiorna lo stato del buffer*/
data = b->buffer[b->readpos];
b->buffer_count--;
b->readpos++;
if(b->readpos >= BUFFER_SIZE)
b->readpos = 0;
/* risveglia eventuali thread (produttori) sospesi al full*/
pthread_cond_signal(&b->buffer_full);
pthread_mutex_unlock(&b->lock);
return data;
}
void *producer (void *data) {
int n;
for (n = 0; n<go; n++) {
printf("\tproduttore ---> %d\n", n);
inserisci(&buffer, n);
}
inserisci(&buffer, OVER);
return (void*) 0;
}
void *consumer (void *data) {
int d = 0;
while(d != OVER) {
d = estrai(&buffer);
printf("consumatore <-- %d\n", d);
}
return (void*) 0;
}
int main(int argc, char* argv[]) {
pthread_t th_a, th_b;
void *retval;
init(&buffer);
if(argc<2)
go = max;
else
go = atoi(argv[argc-1]);
/* creazione thread */
pthread_create(&th_a, NULL, producer, 0);
pthread_create(&th_b, NULL, consumer, 0);
/* attesa teminazione threads creati: */
pthread_join(th_a, &retval);
pthread_join(th_b, &retval);
//printf("%d", (int*)retval);
return 0;
}
__________________
Saigon, shit. I'm still only in Saigon. Ultima modifica di tæo : 06-03-2008 alle 15:40. |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Non è la stessa cosa, l'accesso alla risorsa condivisa (un buffer) è garantito dai semafori pieno/vuoto perché la risorsa condivisa è multipla (al contrario nel problema sopra poteva anche essere una sola), inoltre non c'è alcuna precedenza agli scrittori rispetto ai lettori.
|
|
|
|
|
|
#7 |
|
Member
Iscritto dal: Sep 2005
Messaggi: 82
|
hai ragione, mi sono perso la chiosa sulla precedenza agli scrittori. ma d'altra parte, come ho detto, il listato fa parte di una mia vecchia collezione di sorgenti che avevo provato per imparare le basi della programmazione concorrente. leggendo il titolo del thread mi sono sentito di proporre il risultato, sperando che possa essergli d'aiuto come ispirazione e primo assaggio del problema ma non come una sua soluzione
in ogni caso non ho capito cosa intendi quando parli di semafori.
__________________
Saigon, shit. I'm still only in Saigon. |
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
pthread_cond_t buffer_empty; pthread_cond_t buffer_full; più i rispettivi contatori svolgono una funzione identica a quella delle primitive semaforiche, solo che nei semafori i contatori sono racchiusi all'interno delle primitive. Cioè è la classica rappresentazione di una coda circolare in ambiente a multithreading. |
|
|
|
|
|
|
#9 |
|
Member
Iscritto dal: Sep 2005
Messaggi: 82
|
ok, ora è chiaro
in effetti anche il mutex non è altro che un semaforo (binario), alla fine si ritorna sempre lì cmq grazie per la precisazione
__________________
Saigon, shit. I'm still only in Saigon. |
|
|
|
|
|
#10 |
|
Member
Iscritto dal: Apr 2007
Messaggi: 51
|
Ciao a tutti!
Allora, ho cercato di studiare il problema e di implementare un mio rwlock personale ma.... ci sono andato solo vicino...... Il fatto è che secondo me le funzioni scritte per gestire l'RWLock vanno bene, mi sembrano pure ben fatte! purtroppo una volta applicate hanno un funzionamento alternato (cioè ogni tanto vanno e fanno il loro lavoro, molto più spesso NO A questo punto chiedo l'aiuto di qualunque buonanima voglia mettersi alla prova con un buon debug o con dei consigli, perchè io sto esaurendo le idee. Posto il codice del mio RW Lock applicato al programma che ci è stato dato per testarlo.... file list.c Codice:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "linkedlist.h"
#define YES 1
#define NO 0
typedef char bool;
typedef struct thread_rwlock thread_rwlock_t;
typedef thread_rwlock_t * to_rwl;
struct thread_rwlock {
pthread_mutex_t guardia; /* controllo di accesso */
pthread_cond_t canread; /* posso leggere? */
pthread_cond_t canwrite; /* posso scrivere? */
int r_run; /* lettori attualmente attivi */
int w_run ; /* scrittori attualmente attivi */
int r_wait; /* lettori che aspettano */
int w_wait; /* scrittori che aspettano */
bool to_use; /* controllo errori */
};
int thread_rwlock_init ( to_rwl );
int thread_rwlock_destroy ( to_rwl );
int thread_rwlock_rdlock ( to_rwl );
void thread_rwlock_tryrdlock ( to_rwl );
int thread_rwlock_wrlock ( to_rwl );
void thread_rwlock_trywrlock ( to_rwl );
int thread_rwlock_rdunlock ( to_rwl );
int thread_rwlock_wrunlock ( to_rwl );
thread_rwlock_t RWL;
int main(int argc, char *argv[])
{
int i;
pthread_t *f_tid;
pthread_t *e_tid;
lista_impiegati.next = NULL;
lista_impiegati.nome = (char *)-1;
if(argc >= 2) TRASFER_DELAY = atoi(argv[1]);
if(argc >= 3) AUMENTO_DELAY = atoi(argv[2]);
if(argc >= 4) N_IMPIEGATI = atoi(argv[3]);
if(argc >= 5) N_AUMENTI = atoi(argv[4]);
if(argc >= 6) E_THREADS = atoi(argv[5]);
if(argc >= 7) F_THREADS = atoi(argv[6]);
thread_rwlock_init ( &RWL );
f_tid = (pthread_t *)malloc(sizeof(pthread_t)*F_THREADS);
e_tid = (pthread_t *)malloc(sizeof(pthread_t)*E_THREADS);
printf(" TRASFER_DELAY: %d\n AUMENTO_DELAY: %d\n N_IMPIEGATI: %d\n N_AUMENTI: %d\n E_THREADS: %d\n F_THREADS: %d\n",\
TRASFER_DELAY,AUMENTO_DELAY,N_IMPIEGATI,N_AUMENTI,E_THREADS,F_THREADS);
/* crea la lista degli impiegati */
crea_lista_impiegati();
for(i = 0;i < F_THREADS;i++)
pthread_create(&f_tid[i],NULL,da_aumento_lista_impiegati,crea_lista_aumenti(i*10));
for( i = 0;i < E_THREADS;i++)
pthread_create(&e_tid[i],NULL,trasferisci_lista_impiegati,crea_lista_trasfer(i));
for(i = 0; i < F_THREADS;i++)
pthread_join(f_tid[i],NULL);
for(i = 0; i < E_THREADS;i++)
pthread_join(e_tid[i],NULL);
conta_trovati(-1);
conta_conflitti(-1);
thread_rwlock_destroy ( &RWL );
printf("Fatto\n");
exit(0);
}
void conta_conflitti(int i)
{
static int count = 0,max_count = 0;
static pthread_mutex_t conta_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&conta_lock);
count += i;
if( i == -1 ) printf("Conflitti: %d\n",max_count);
if( count > max_count )
max_count = count;
pthread_mutex_unlock(&conta_lock);
}
void conta_trovati(int i)
{
static int count = 0, max_count = 0;
static pthread_mutex_t conta_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&conta_lock);
count += i;
if( i == -1 ) printf("Totale trasferimenti + aumenti : %d\n",max_count);
if( count > max_count )
max_count = count;
pthread_mutex_unlock(&conta_lock);
}
void stampa_lista_impiegati(impiegato_t *p)
{
int i = 0;
while( p != NULL ) {
printf("(%s %d) ",p->nome,p->salario);
p = p->next;
i++;
if( (i % 5) == 0 ) printf("\n");
}
}
impiegato_t *trova_impiegato(char *nome)
{
impiegato_t *p = &lista_impiegati;
impiegato_t *p1;
p1 = p->next;
while(p1 != NULL) {
if( strcmp(p1->nome,nome) == 0 )
{
conta_trovati(1);
return(p);
}
p = p1;
p1 = p->next;
}
return(NULL);
}
void crea_lista_impiegati()
{
int i;
char s[20], *s1;
for(i = 0; i < N_IMPIEGATI;i++) {
sprintf(s,"Jan_%d",i);
s1 = (char *)malloc(strlen(s)+1);
strcpy(s1,s);
aggiungi_lista_impiegati(s1);
}
}
void aggiungi_lista_impiegati(char *nome)
{
impiegato_t *p;
p = (impiegato_t *)malloc(sizeof(impiegato_t));
p->nome = nome;
p->salario = 0;
p->next = lista_impiegati.next;
lista_impiegati.next = p;
}
void da_aumento_impiegato(impiegato_t *p)
{
if( p == NULL ) return;
p->next->salario++;
delay(AUMENTO_DELAY,0);
}
void *da_aumento_lista_impiegati(void *arg)
{
impiegato_t *p;
impiegato_t *lista = (impiegato_t *)arg;
while( lista != NULL ) {
thread_rwlock_rdlock ( &RWL );
p = trova_impiegato(lista->nome);
da_aumento_impiegato(p);
lista = lista->next;
thread_rwlock_rdunlock ( &RWL );
delay(0,0);
}
return NULL;
}
impiegato_t *crea_lista_aumenti(int seed1)
{
int i,r;
unsigned int seed = (int)seed1;
char s[20],*s1;
impiegato_t *p,lista;
lista.next = NULL;
for( i = 0; i < N_AUMENTI; i++ ) {
r = rand_r(&seed) % N_IMPIEGATI;
sprintf(s,"Jan_%d",r);
s1 = (char *)malloc(strlen(s)+1);
strcpy(s1,s);
p = (impiegato_t *)malloc(sizeof(impiegato_t));
p->nome = s1;
p->next = lista.next;
lista.next = p;
}
return(lista.next);
}
void trasferisci_impiegato(impiegato_t *p)
{
impiegato_t *p1;
p1 = p->next;
p->next = p1->next;
printf("Trasferimento: (%s %d)\n",p1->nome,p1->salario);
free(p1->nome);
free(p1);
delay(TRASFER_DELAY,0);
return;
}
void *trasferisci_lista_impiegati(void *arg)
{
impiegato_t *p;
impiegato_t *lista = (impiegato_t *)arg;
while(lista != NULL ) {
thread_rwlock_wrlock ( &RWL );
p = trova_impiegato(lista->nome);
if (p) trasferisci_impiegato(p);
lista = lista->next;
thread_rwlock_wrunlock ( &RWL );
delay(0,0);
}
return NULL;
}
impiegato_t *crea_lista_trasfer(int s)
{
return(crea_lista_aumenti(s));
}
void delay(int sleep_ms,int cpu_us)
{
int i, cicli = cpu_us * 8;
volatile int j;
struct timespec tv;
if( sleep_ms != 0) {
tv.tv_sec = sleep_ms/1000;
tv.tv_nsec = (sleep_ms % 1000)*1000000;
nanosleep(&tv,NULL);
}
if( cpu_us != 0 )
for( i = 0; i < cicli; i++) j++;
}
/* RW-Lock function */
int thread_rwlock_init ( to_rwl rwl )
{
int ok; /* controllo errori */
rwl->r_run = 0;
rwl->w_run = 0;
rwl->r_wait = 0;
rwl->w_wait = 0;
ok = pthread_mutex_init ( &rwl->guardia, NULL );
if ( ok )
{
/* se fallisce la creazione ritorno un errore */
printf ("\nErrore inizializzazione mutex\n");
return ok;
}
ok = pthread_cond_init ( &rwl->canread, NULL );
if ( ok )
{
/* se fallisce la creazione distruggo il mutex e ritorno un errore */
printf ("\nErrore inizializzazione variabile (I can read ?)\n");
pthread_mutex_destroy ( &rwl->guardia );
return ok;
}
ok = pthread_cond_init ( &rwl->canwrite, NULL );
if ( ok )
{
/* se fallisce la creazione distruggo il mutex e la precedente variabile condizionale e ritorno un errore */
printf ("\nErrore inizializzazione variabile (I can read ?)\n");
pthread_mutex_destroy ( &rwl->guardia );
pthread_cond_destroy ( &rwl->canread );
return ok;
}
rwl->to_use = YES;
return 0;
}
int thread_rwlock_destroy ( to_rwl rwl )
{
int ok;
/* check validità dell'RW-Lock, mi serve per escludere eventuali usi futuri di una struct thread_rwlock in fase di deallocazione */
if ( !rwl->to_use )
{
printf ("\nL'RW-Lock e' corrotto!!!\n");
return -1;
}
/* provo a prendere possesso dell'RW-Lock */
ok = pthread_mutex_trylock ( &rwl->guardia );
if ( ok )
{
printf ("\nL'RW-Lock è occupato, impossibile accedere\n");
return ok;
}
/* se arrivo a questo punto la guardia è locked, controllo se ci sono threads attive */
if ( rwl->r_run || rwl->w_run )
{
printf ("\nCi sono ancora thread attive, non posso distruggere l'RW-Lock\n");
ok = pthread_mutex_unlock ( &rwl->guardia );
return ok;
}
/* se arrivo a questo punto la guardia è locked, controllo se ci sono threads in waiting */
if ( rwl->r_wait || rwl->w_wait )
{
printf ("\nCi sono ancora thread in coda, non posso distruggere l'RW-Lock\n");
ok = pthread_mutex_unlock ( &rwl->guardia );
return ok;
}
/* se e' tutto a posto setto la validita' a NO e sblocco */
rwl->to_use = NO;
pthread_mutex_unlock ( &rwl->guardia );
ok = pthread_mutex_destroy ( &rwl->guardia );
if ( !ok )
{
printf ("\nErrore distruzione mutex GUARDIA\n");
return -1;
}
ok = pthread_cond_destroy ( &rwl->canread );
if ( !ok )
{
printf ("\nErrore distruzione variabile condizionale (I can read?)\n");
return -1;
}
ok = pthread_cond_destroy ( &rwl->canwrite );
if ( !ok )
{
printf ("\nErrore distruzione variabile condizionale (I can write?)\n");
return -1;
}
return 0;
}
int thread_rwlock_rdlock ( to_rwl rwl )
{
int ok;
/* check validità dell'RW-Lock */
if ( !rwl->to_use )
{
printf ("\nL'RW-Lock e' corrotto!!!\n");
return -1;
}
/* provo a prendere possesso dell'RW-Lock */
do {
ok = pthread_mutex_trylock ( &rwl->guardia );
/* se l'RW-Lock è EBUSY, allora incremento conta_conflitti */
if ( ok )
{
conta_conflitti(1);
}
} while ( ok );
/* a questo punto ho il lock sul mutex, devo controllare la condition canread */
thread_rwlock_tryrdlock ( rwl );
return 0;
}
void thread_rwlock_tryrdlock ( to_rwl rwl )
{
/* controllo e aggiorno i registri */
if ( rwl->w_wait == 0 && rwl->w_run == 0 )
{
rwl->r_run++;
pthread_mutex_unlock ( &rwl->guardia );
}
else
{
rwl->r_wait++;
pthread_cond_wait ( &rwl->canread, &rwl->guardia );
pthread_mutex_unlock ( &rwl->guardia );
}
}
int thread_rwlock_wrlock ( to_rwl rwl )
{
int ok;
/* check validità dell'RW-Lock */
if ( !rwl->to_use )
{
printf ("\nL'RW-Lock e' corrotto!!!\n");
return -1;
}
/* provo a prendere possesso dell'RW-Lock */
do {
ok = pthread_mutex_trylock ( &rwl->guardia );
/* se l'RW-Lock è EBUSY, allora incremento conta_conflitti */
if ( ok )
{
conta_conflitti(1);
}
} while ( ok );
/* a questo punto ho il lock sul mutex, devo controllare la condition canwrite */
thread_rwlock_trywrlock ( rwl );
return 0;
}
void thread_rwlock_trywrlock ( to_rwl rwl )
{
/* controllo e aggiorno i registri */
if ( rwl->w_wait == 0 && rwl->w_run == 0 && rwl->r_run == 0 )
{
rwl->w_run++;
pthread_mutex_unlock ( &rwl->guardia );
}
else
{
rwl->w_wait++;
pthread_cond_wait ( &rwl->canwrite, &rwl->guardia );
pthread_mutex_unlock ( &rwl->guardia );
}
}
int thread_rwlock_rdunlock ( to_rwl rwl )
{
int ok;
/* check validità dell'RW-Lock */
if ( !rwl->to_use )
{
printf ("\nL'RW-Lock e' corrotto!!!\n");
return -1;
}
/* provo a prendere possesso dell'RW-Lock */
do {
ok = pthread_mutex_trylock ( &rwl->guardia );
/* se l'RW-Lock è EBUSY, allora incremento conta_conflitti */
if ( ok )
{
conta_conflitti(1);
}
} while ( ok );
/* a questo punto ho il lock sul mutex, devo aggiornare i registri e poi uscire */
rwl->r_run--;
pthread_mutex_unlock ( &rwl->guardia );
if ( !rwl->r_run && rwl->w_wait )
pthread_cond_signal ( &rwl->canwrite );
return 0;
}
int thread_rwlock_wrunlock ( to_rwl rwl )
{
int ok;
/* check validità dell'RW-Lock */
if ( !rwl->to_use )
{
printf ("\nL'RW-Lock e' corrotto!!!\n");
return -1;
}
/* provo a prendere possesso dell'RW-Lock */
do {
ok = pthread_mutex_trylock ( &rwl->guardia );
/* se l'RW-Lock è EBUSY, allora incremento conta_conflitti */
if ( ok )
{
conta_conflitti(1);
}
} while ( ok );
/* a questo punto ho il lock sul mutex, devo aggiornare i registri e poi uscire */
rwl->w_run--;
pthread_mutex_unlock ( &rwl->guardia );
if ( rwl->w_wait )
pthread_cond_signal ( &rwl->canwrite );
else
pthread_cond_broadcast ( &rwl->canread );
return 0;
}
Codice:
#ifndef _LINKEDLIST_H__
#define _LINKEDLIST_H__
typedef struct impiegato impiegato_t;
struct impiegato {
char *nome; /* nome impiegato JAN### */
int salario; /* salario percepito */
struct impiegato *next; /* puntatore alla struttura successiva */
};
impiegato_t lista_impiegati;
int E_THREADS = 1; /* numero di thread che eseguono il trasferimento */
int F_THREADS = 10; /* numero di thread che eseguono l'aumento */
int N_IMPIEGATI = 1000; /* numero di impiegati iniziali */
int N_AUMENTI = 100; /* numero di impiegati che ricevono l'aumento */
int AUMENTO_DELAY = 100; /* ritardo per operazione aumento in ms */
int TRASFER_DELAY = 100; /* ritardo per operazione di trasferimento */
/* prototipi di funzione */
void conta_conflitti(int i);
void conta_trovati(int i);
void stampa_lista_impiegati(impiegato_t *p);
impiegato_t *trova_impiegato(char *nome);
void aggiungi_lista_impiegati(char *nome);
void crea_lista_impiegati();
void da_aumento_impiegato(impiegato_t *p);
void *da_aumento_lista_impiegati(void *arg);
impiegato_t *crea_lista_aumenti(int seed1);
void trasferisci_impiegato(impiegato_t *p);
void *trasferisci_lista_impiegati(void *arg);
impiegato_t *crea_lista_trasfer(int s);
void delay(int sleep_ms,int cpu_us);
#endif
Grazie a tutti
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
L'unico consiglio che ti posso dare è andare per gradi e non scrivere tutto il codice in una volta sola.
Secondo me ha poco senso implementare il trylock, magari lo puoi fare dopo, prima implementa solo lock e unlock. Non so a cosa ti serva conta_conflitti, me lo puoi spiegare ? |
|
|
|
|
|
#12 |
|
Member
Iscritto dal: Apr 2007
Messaggi: 51
|
Ciao, adesso provo a seguire il tuo consiglio e a provare prima la soluzione con lock e unlock (not trylock).
Conta_conflitti fa parte delle funzioni date dal professore, ed è in relazione proprio con i trylock, ovvero ogni volta che una thread effettua un trylock ritornando EBUSY, allora viene chiamata contaconflitti(1) che dovrebbe, alla fine (dopo la chiamata conta_conflitti (-1) nel main) printare su schermo in numero di volte che le varie thread non hanno potuto accedere direttamente alla struttura dati perchè già bloccata da un'altra... Purtroppo il progetto che ci è stato dato è pensato per "vedere" il funzionamento delle Pthread e i prob di sincronizzazione, ma la "logica" del programma è decisamente carente (e questo, per me personalmente, è un problema, perchè perdo tempo anche solo a capire dove si vuole andare a parare..) La "prima versione" del progetto era di effettuare la sincronizzazione usando 1 SOLO MUTEX GLOBALE, ovvero mettendo un bel lock all'ACCESSO alla lista! che senso ha? allora vuol dire che le thread accedono alla struttura dati una sola alla volta, indipendentemente dal loro compito... quindi dove vanno a finire i vantaggi dell'esecuzione in parallelo???? La seconda parte è appunto quella di implementare un nostro rw-lock usando mutex e variable condition.... ok, ci sta! ma poi ci chiede di applicarlo al programma precedente al posto del mutex globale, e anche qui... Dato che le ETHREAD modificano la lista (cancellando elementi) sono i nostri "writers", per semplice esclusione le FTHREAD sono le readers (come confermato dal prof). Problema: è vero che le fthread non cambiano le DIMENSIONI della lista concatenata, ma vanno comunque a SCRIVERE all'interno di un campo della "struct elemento"... quindi in teoria (almeno per quello che ho capito studiando) non sono proprio solo readers, e anche il loro accesso agli elementi andrebbe regolamentato, in quanto diversamente potrebbero accadere context switch nel momento sbagliato e 2 o più FTHREAD che vogliono incrementare lo stipendio allo stesso elemento potrebbero "sbagliare"..... Insomma, per me è proprio il testo dell'esercizio che è un po' confuso! ma è il penultimo progetto prima dell'esame ho fatto bene gli altri e voglio far bene anche questo.... Va beh, polemiche a parte ho da chiedere una cosa specifica... quando una thread mi va in wait su una variable conditions, rilascia il lock del mutex. poi quando un'altra thread manda un signal sulla conditions... la thread che si risveglia acquisisce o TENTA di ACQUISIRE nuovamente il mutex, e poi da dove riprende la sua esecuzione? dall'istruzione sucessiva alla chiamata di wait? oppure "testa" nuovamente la condition(finendo eventualmente di nuovo in wait) ? Ciao e grazie |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
L'esecuzione riparte da dopo la pthread_cond_wait con la mutex acquisita.
|
|
|
|
|
|
#14 |
|
Member
Iscritto dal: Apr 2007
Messaggi: 51
|
ciao, alla fine credo di essere riuscito a mettere tutto a posto!
Grazie per tutti i vostri consigli... Ora vorrei chiedere un altro favore, se allego i file che ho scritto, non è che ci potreste dare una occhiata? Io li ho fatti e mi sembrano corretti, ma per un po' di test alle volte è meglio chiedere aiuto a persone più esperte! Sono anche contattabile in pvt all'indirizzo [email protected] Grazie 1000 a todos!!!! CIAOOOOOOOOOOOOOOOOOOOOOOOOOO |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 07:40.




















