El algoritmo de Peterson del es un algoritmo de la programación concurrente para la exclusión mutua que permite que dos o más procesos compartan un recurso single-use sin conflicto, usar solamente la memoria compartida para la comunicación. Fue formulado por el Gary Peterson en el 1981 en la universidad de Rochester . Mientras que la formulación original de Peterson trabajó con solamente dos procesos, el algoritmo se puede generalizar para más de dos, según lo discutido en " Revisión de los sistemas operativos, " de enero de 1990 (“prueba de un algoritmo de la exclusión mutua”, M Hofri);.
Al trabajar en el nivel del hardware, el algoritmo de Peterson no es típicamente necesario alcanzar el acceso atómico. El que viene el RAM de dos puertos (DPRAM) equipado de un Prueba-y-fijó o la instrucción equivalente, que los procesadores utilizan cuando memoria de acceso. Por lo tanto las operaciones concurrentes mantienen el estado correcto durante accesos simultáneos. Las técnicas del software especial no se requieren.
bandera = 0 bandera = 0 vuelta = 0 P0: bandera = 1 P1: bandera = 1 vuelta = 1 vuelta = 0 mientras que (== de la vuelta del && de la bandera 1); mientras que (== 0 de la vuelta del && de la bandera); // no hace que nada // no hace nada sección crítica de // de la sección crítica de // … … extremo de // del extremo de // de la sección crítica de la sección crítica bandera = 0 banderas = 0
El algoritmo utiliza dos variables, banderas del y vueltas del . Un valor de la bandera de 1 indica que el proceso quiere incorporar la sección crítica . La vuelta variable celebra la identificación del proceso de quién vuelta es. La entrada a la sección crítica se concede para el proceso P0 si no hace P1 querer incorporar su sección crítica o si P1 ha dado prioridad a P0 fijando vuelta a 0.
El algoritmo satisface los tres criterios esenciales de la exclusión mutua :
/* * Fuente del ANSI C89, puesta en práctica del estilo de KNF del algoritmo de Peterson. * * Derechos reservados (c) 2005, Matthew Mondor * Lanzado en el public domain (puede ser autorizado debajo del GFDL). * * Fijar por favor cualquier insecto según lo necesitado, preservando el estilo de KNF y este comentario, * a menos que esté considerado incómodo en este caso usted puede hacer lo que usted quiere * con el código. * el
incluye el
pa_desc del struct { internacional volátil *f0, *f1; último de la internacional; };
pa_init vacío (vacío); pa_desc_init vacío (pa_desc del struct *, internacional); pa_desc_lock vacío (pa_desc del struct *); pa_desc_unlock vacío (pa_desc del struct *);
*thread0_main vacío (vacío *); *thread1_main vacío (vacío *); threadx_critical vacío (vacío);
cañería de la internacional (internacional, carbón de leña **);
volátil estático internacional pa_f0, pa_f1, pa_last;
/* compartido * definir los CUBOS 100 soldado enrollado en el ejército de la internacional, g;
/* * Inicializa el sistema del PA. Para ser llamado por el proceso una vez antes * descriptores de incialización del PA. * vacío pa_init (vacío) {
pa_f0 = pa_f1 = pa_last = 0; }
/* * Inicializa un descriptor del PA para uso de un hilo de rosca. * Un hilo de rosca debe utilizar la identificación 0 y la otra una identificación 1. * vacío pa_desc_init (*d del pa_desc del struct, identificación de la internacional) {
afirmar (== 0 de la identificación || == de la identificación 1);
si (== 0 de la identificación) { d->f0 = &pa_f0; d->f1 = &pa_f1; d->last = 1; } si (== de la identificación 1) { d->f0 = &pa_f1; d->f1 = &pa_f0; d->last = 0; } }
vacío pa_desc_lock (*d) del pa_desc del struct {
para (*d->f0 = 1, pa_last = d->last; *d->f1 d->last del == del pa_last del && del == 1; ); }
vacío pa_desc_unlock (*d) del pa_desc del struct {
*d->f0 = 0; }
/* * Lazo principal del primer hilo de rosca concurrente * /* ARGSUSED * vacío * thread0_main (*args vacíos) { pa_desc d del struct;
pa_desc_init (&d, 0);
para (; ;) { pa_desc_lock (&d); threadx_critical (); pa_desc_unlock (&d); }
/* NOTREACHED * FALTA DE INFORMACIÓN de vuelta; }
/* * Lazo principal del segundo hilo de rosca concurrente * /* ARGSUSED * vacío * thread1_main (*args vacíos) { pa_desc d del struct;
pa_desc_init (&d, 1);
para (; ;) { pa_desc_lock (&d); threadx_critical (); pa_desc_unlock (&d); }
/* NOTREACHED * FALTA DE INFORMACIÓN de vuelta; }
/* * Función crítica que tendría normalmente ediciones de la concurrencia si dos * los hilos de rosca la ejecutaron sin la fijación. * vacío threadx_critical (vacío) { internacional i;
/* hacen algo que tendría normalmente ediciones duales de la concurrencia * para (i = 0; i < CUBOS; i++) g = gi++; para (i = 0; i < CUBOS; i++) printf (vacío) (" g = %d \ n", i, g); }
/* * Programa de prueba que demuestra que la concurrencia dual puede ser alcanzada * sin la fijación usar el algoritmo de Peterson. Funcionamos con dos hilos de rosca concurrentes * que realizan voluntariamente operaciones sensibles de la concurrencia en compartido * región de memoria (soldado enrollado en el ejército, g). * /* ARGSUSED * internacional cañería (argc de la internacional, carbón de leña ** argv) { pthread_t tid1, tid2; tattr del pthread_attr_t;
soldado enrollado en el ejército = 0; pa_init ();
pthread_attr_init (&tattr); pthread_attr_setdetachstate (&tattr, 0);
Nota de/*: un uso verdadero realizaría el repaso de las faltas * pthread_create (&tid1, &tattr, thread0_main, FALTA DE INFORMACIÓN); pthread_create (&tid2, &tattr, thread1_main, FALTA DE INFORMACIÓN);
pthread_join (tid1, FALTA DE INFORMACIÓN); pthread_join (tid2, FALTA DE INFORMACIÓN); /* NOTREACHED *
EXIT_SUCCESS de vuelta; }
La mayoría de las tales CPU también tienen cierta clase de la operación atómica garantizada, tal como XCHG en procesadores X86 y Carga-Acoplamiento/ Almacenar-Condicional en la alfa, las MIPS, el PowerPC, y otras arquitecturas. Se piensan estas instrucciones de proporcionar una manera de construir primitivos de la sincronización más eficientemente que puede ser hecho con acercamientos puros de la memoria compartida.
| Random links: | Modo raro | Acorazado japonés Yamato | Lista de suburbios de Hobart | Día del Juicio Final de WWE | Pared-de--Regla |