Introduction
The threads with common resources have some problems , but there are too how to resolve them.the programer could use critical sections or semaphores for controling how many threads are using a resource.
Problem: Pacman game
Pacman game has many "objects" in the labyrinth: Ghosts, points and its own. These objects have common access to structure: the labyrinth ( one matrix of characters ).
In the first program is possible that one thread overwrite a symbol of other thread. These procedures "iniciarPacman", "iniciarFantasmas" and "iniciarPuntos" are used for finding a free position and then write a symbol there.
Original code
#include < stdio.h >
#include < conio.h >
#include < windows.h >
#include < stdlib.h >
#define COLUMNAS 10
#define RENGLONES 10
#define CANT_FANTASMAS 5
#define CANT_PUNTOS 20
#define CANTIDAD_HILOS 3
struct t_fantasma
{
int col;
int ren;
};
struct t_puntos
{
int col;
int ren;
};
typedef struct t_fantasma TFANTASMA;
typedef struct t_puntos TPUNTOS;
void leerTablero( void );
void mostrarTablero( void );
void iniciarFantasmas(void);
DWORD WINAPI metodo1(LPVOID param);
DWORD WINAPI metodo2(LPVOID param);
DWORD WINAPI metodo3(LPVOID param);
void iniciarPacman(void);
void iniciarPuntos(void);
void verificarPartesTablero(void);
char tablero[ RENGLONES ][ COLUMNAS ]; //10x10 character matrix
TFANTASMA fantasmas[ CANT_FANTASMAS ]; //ghosts
TPUNTOS puntos[ CANT_PUNTOS ]; //points for pacman
void main()
{
HANDLE hilos[ CANTIDAD_HILOS ];
clrscr();
randomize();
leerTablero();
hilos[2] = CreateThread( NULL, 0, metodo3, NULL, 0, NULL); //put down points
hilos[1] = CreateThread( NULL, 0, metodo2, NULL, 0, NULL); //put down gost
hilos[0]= CreateThread( NULL, 0, metodo1, NULL, 0, NULL ); //put down pacman
WaitForMultipleObjects(2, hilos, 1, INFINITE );
printf("\n");
mostrarTablero();
verificarPartesTablero();
}
void verificarPartesTablero()
{
int c,r;
int contPacman=0, contFantasmas=0, contPuntos=0;
for(r=0; r< RENGLONES ; r+=1 )
{
for( c=0; c< COLUMNAS ; c+=1 )
{
switch ( tablero[r][c] )
{
case '#': contFantasmas+=1; break;
case '.': contPuntos+=1; break;
case '@': contPacman+=1; break;
}
}
}
printf("\n%i,%i,%i", contPacman, contFantasmas, contPuntos );
}
void iniciarPacman()
{
int col, ren;
do
{
col= random( COLUMNAS );
ren= random( RENGLONES );
} while ( tablero[ ren ] [ col ] != ' ' );
tablero[ ren ][ col ]= '@';
}
void iniciarFantasmas()
{
int i;
for(i=0; i< CANT_FANTASMAS ; i+=1 )
{
do
{
fantasmas[i].col= random( COLUMNAS );
fantasmas[i].ren= random( RENGLONES );
} while ( tablero[ fantasmas[i].ren ] [ fantasmas[i].col ] != ' ' );
tablero[ fantasmas[i].ren ] [ fantasmas[i].col ]='#';
}
}
void iniciarPuntos()
{
int i;
for(i=0; i< CANT_PUNTOS ; i+=1 )
{
do
{
puntos[i].col= random( COLUMNAS );
puntos[i].ren= random( RENGLONES );
} while ( tablero[ puntos[i].ren ] [ puntos[i].col ] != ' ' );
tablero[ puntos[i].ren ] [ puntos[i].col ]='.';
}
}
void leerTablero()
{
int c, r;
FILE *archivo;
archivo= fopen("tablero.txt","rt");
for(r=0; r< RENGLONES ; r+=1 )
{
for( c=0; c< COLUMNAS ; c+=1 )
{
fscanf(archivo, "%c", &tablero[ r ][ c ] );
tablero[ r ][ c ]= (tablero[ r ][ c ]=='1'?' ':tablero[ r ][ c ]);
//printf("%c", tablero[ r ][ c ] );
}
fscanf(archivo, "\n", NULL );
//printf("\n");
}
fclose( archivo );
}
void mostrarTablero()
{
int c, r;
for(r=0; r< RENGLONES ; r+=1 )
{
for( c=0; c< COLUMNAS ; c+=1 )
{
printf("%c", tablero[ r ][ c ] );
}
printf("\n");
}
}
DWORD WINAPI metodo1(LPVOID param)
{
iniciarPacman();
return 0;
}
DWORD WINAPI metodo2(LPVOID param)
{
iniciarFantasmas();
return 0;
}
DWORD WINAPI metodo3(LPVOID param)
{
iniciarPuntos();
return 0;
}
Critical section
The next code define three critical sections in the procedures "iniciarPacman", "iniciarFantasmas" and "iniciarPuntos"
#include < stdio.h >
#include < conio.h >
#include < windows.h >
#include < stdlib.h >
#define COLUMNAS 10
#define RENGLONES 10
#define CANT_FANTASMAS 5
#define CANT_PUNTOS 20
#define CANTIDAD_HILOS 3
struct t_fantasma
{
int col;
int ren;
};
struct t_puntos
{
int col;
int ren;
};
typedef struct t_fantasma TFANTASMA;
typedef struct t_puntos TPUNTOS;
void leerTablero( void );
void mostrarTablero( void );
void iniciarFantasmas(void);
DWORD WINAPI metodo1(LPVOID param);
DWORD WINAPI metodo2(LPVOID param);
DWORD WINAPI metodo3(LPVOID param);
void iniciarPacman(void);
void iniciarPuntos(void);
int verificarPartesTablero(void);
char tablero[ RENGLONES ][ COLUMNAS ]; //el tablero es una matriz de 10x10 caracteres
TFANTASMA fantasmas[ CANT_FANTASMAS ]; //conjunto de fantasmas
TPUNTOS puntos[ CANT_PUNTOS ];
CRITICAL_SECTION sc1;
CRITICAL_SECTION sc2;
CRITICAL_SECTION sc3;
void main()
{
HANDLE hilos[ CANTIDAD_HILOS ];
clrscr();
randomize();
leerTablero();
InitializeCriticalSection( &sc1 ); // critical section begin
InitializeCriticalSection( &sc2 ); // critical section begin
InitializeCriticalSection( &sc3 ); // critical section begin
hilos[2] = CreateThread( NULL, 0, metodo3, NULL, 0, NULL); //put down points
hilos[1] = CreateThread( NULL, 0, metodo2, NULL, 0, NULL); //put down gost
hilos[0]= CreateThread( NULL, 0, metodo1, NULL, 0, NULL ); //put down pacman
WaitForMultipleObjects(CANTIDAD_HILOS, hilos, 1, INFINITE );
DeleteCriticalSection( &sc1 ); // critical section end
DeleteCriticalSection( &sc2 ); // critical section end
DeleteCriticalSection( &sc3 ); // critical section end
mostrarTablero();
}
void iniciarPacman()
{
int col, ren;
EnterCriticalSection( &sc1 );
do
{
col= random( COLUMNAS );
ren= random( RENGLONES );
} while ( tablero[ ren ] [ col ] != ' ' );
tablero[ ren ][ col ]= '@';
LeaveCriticalSection( &sc1 );
}
void iniciarFantasmas()
{
int i;
for(i=0; i< CANT_FANTASMAS ; i+=1 )
{
EnterCriticalSection( &sc2 );
do
{
fantasmas[i].col= random( COLUMNAS );
fantasmas[i].ren= random( RENGLONES );
} while ( tablero[ fantasmas[i].ren ] [ fantasmas[i].col ] != ' ' );
tablero[ fantasmas[i].ren ] [ fantasmas[i].col ]='#';
LeaveCriticalSection( &sc2 );
}
}
void iniciarPuntos()
{
int i;
for(i=0; i< CANT_PUNTOS ; i+=1 )
{
EnterCriticalSection( &sc3 );
do
{
puntos[i].col= random( COLUMNAS );
puntos[i].ren= random( RENGLONES );
} while ( tablero[ puntos[i].ren ] [ puntos[i].col ] != ' ' );
tablero[ puntos[i].ren ] [ puntos[i].col ]='.';
LeaveCriticalSection( &sc3 );
}
}
void leerTablero()
{
int c, r;
FILE *archivo;
archivo= fopen("tablero.txt","rt");
for(r=0; r< RENGLONES ; r+=1 )
{
for( c=0; c< COLUMNAS ; c+=1 )
{
fscanf(archivo, "%c", &tablero[ r ][ c ] );
tablero[ r ][ c ]= (tablero[ r ][ c ]=='1'?' ':tablero[ r ][ c ]);
//printf("%c", tablero[ r ][ c ] );
}
fscanf(archivo, "\n", NULL );
//printf("\n");
}
fclose( archivo );
}
void mostrarTablero()
{
int c, r;
for(r=0; r< RENGLONES ; r+=1 )
{
for( c=0; c< COLUMNAS ; c+=1 )
{
printf("%c", tablero[ r ][ c ] );
}
printf("\n");
}
}
DWORD WINAPI metodo1(LPVOID param)
{
iniciarPacman();
return 0;
}
DWORD WINAPI metodo2(LPVOID param)
{
iniciarFantasmas();
return 0;
}
DWORD WINAPI metodo3(LPVOID param)
{
iniciarPuntos();
return 0;
}
Semaphores
The next code define one binary semaphore for controling access to labyrinth in the same procedures.
#include < stdio.h >
#include < conio.h >
#include < windows.h >
#include < stdlib.h >
#define COLUMNAS 10
#define RENGLONES 10
#define CANT_FANTASMAS 5
#define CANT_PUNTOS 20
#define CANTIDAD_HILOS 3
struct t_fantasma
{
int col;
int ren;
};
struct t_puntos
{
int col;
int ren;
};
typedef struct t_fantasma TFANTASMA;
typedef struct t_puntos TPUNTOS;
void leerTablero( void );
void mostrarTablero( void );
void iniciarFantasmas(void);
DWORD WINAPI metodo1(LPVOID param);
DWORD WINAPI metodo2(LPVOID param);
DWORD WINAPI metodo3(LPVOID param);
void iniciarPacman(void);
void iniciarPuntos(void);
int verificarPartesTablero(void);
char tablero[ RENGLONES ][ COLUMNAS ]; //el tablero es una matriz de 10x10 caracteres
TFANTASMA fantasmas[ CANT_FANTASMAS ]; //conjunto de fantasmas
TPUNTOS puntos[ CANT_PUNTOS ];
HANDLE semaforo;
void main()
{
HANDLE hilos[ CANTIDAD_HILOS ];
clrscr();
randomize();
leerTablero();
//definir semaphore
semaforo= CreateSemaphore( NULL, 1,1, NULL );
hilos[2] = CreateThread( NULL, 0, metodo3, NULL, 0, NULL); //put down points
hilos[1] = CreateThread( NULL, 0, metodo2, NULL, 0, NULL); //put down gost
hilos[0]= CreateThread( NULL, 0, metodo1, NULL, 0, NULL ); //put down pacman
WaitForMultipleObjects(CANTIDAD_HILOS, hilos, 1, INFINITE );
mostrarTablero();
}
void iniciarPacman()
{
int col, ren;
WaitForSingleObject( semaforo, INFINITE );
do
{
col= random( COLUMNAS );
ren= random( RENGLONES );
} while ( tablero[ ren ] [ col ] != ' ' );
tablero[ ren ][ col ]= '@';
ReleaseSemaphore( semaforo, 1, NULL );
}
void iniciarFantasmas()
{
int i;
for(i=0; i< CANT_FANTASMAS ; i+=1 )
{
WaitForSingleObject( semaforo, INFINITE );
do
{
fantasmas[i].col= random( COLUMNAS );
fantasmas[i].ren= random( RENGLONES );
} while ( tablero[ fantasmas[i].ren ] [ fantasmas[i].col ] != ' ' );
tablero[ fantasmas[i].ren ] [ fantasmas[i].col ]='#';
ReleaseSemaphore( semaforo, 1, NULL );
}
}
void iniciarPuntos()
{
int i;
for(i=0; i< CANT_PUNTOS ; i+=1 )
{
WaitForSingleObject( semaforo, INFINITE );
do
{
puntos[i].col= random( COLUMNAS );
puntos[i].ren= random( RENGLONES );
} while ( tablero[ puntos[i].ren ] [ puntos[i].col ] != ' ' );
tablero[ puntos[i].ren ] [ puntos[i].col ]='.';
ReleaseSemaphore( semaforo, 1, NULL );
}
}
void leerTablero()
{
int c, r;
FILE *archivo;
archivo= fopen("tablero.txt","rt");
for(r=0; r< RENGLONES ; r+=1 )
{
for( c=0; c< COLUMNAS ; c+=1 )
{
fscanf(archivo, "%c", &tablero[ r ][ c ] );
tablero[ r ][ c ]= (tablero[ r ][ c ]=='1'?' ':tablero[ r ][ c ]);
//printf("%c", tablero[ r ][ c ] );
}
fscanf(archivo, "\n", NULL );
//printf("\n");
}
fclose( archivo );
}
void mostrarTablero()
{
int c, r;
for(r=0; r< RENGLONES ; r+=1 )
{
for( c=0; c< COLUMNAS ; c+=1 )
{
printf("%c", tablero[ r ][ c ] );
}
printf("\n");
}
}
DWORD WINAPI metodo1(LPVOID param)
{
iniciarPacman();
return 0;
}
DWORD WINAPI metodo2(LPVOID param)
{
iniciarFantasmas();
return 0;
}
DWORD WINAPI metodo3(LPVOID param)
{
iniciarPuntos();
return 0;
}
Conclusions
The use of semaphores and critical sections is simple and usefull. We have to use them when many threads use the same resources.
References
[3] Borland C++ Compiler version 5.5 Free Download. Embarcadero developer network. http://edn.embarcadero.com/article/20633
[4] Intel Software Network, Parallel Programming and Multi-Core. Multi - core Programming for Academia ( spanish version ). Programango Hilos en Windows. http://software.intel.com/en-us/articles/multi-core-programing-for-academia-spanish-version-1/28/oct/2008
Compartiendo para dos mundos
Hablando de programación paralela.
Tutoriales en: https://www.youtube.com/user/jambrizgdl
Twitter: @dogoteacher
No hay comentarios:
Publicar un comentario
Are you ready?