ARQUITECTURAS
CLIENTE/SERVIDOR Cliente y Servidores Sincronizados
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Contenido
• Procesos
• Semáforos
• Sincronización
• Lectura y Escritura de Archivos
• Servidores Orientados a Conexión
• Servidores No Orientados a Conexión
Procesos
• Un programa en ejecución es un proceso.
• Un proceso es cualquier secuencia de operaciones que
están ejecutándose en memoria activa, realizando una o
varias instrucciones sobre ciertos datos.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Los procesos pueden ser concurrentes o
paralelos.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Programación concurrente
• Cada proceso representa un programa secuencial que ejecuta
una serie de instrucciones.
• Al ejecutarse un programa secuencial, éste sigue un solo “hilo
de control” (thread), esto es se inicia con una operación
atómica (indivisible) del proceso y se mueve a través del
proceso conforme las operaciones se van ejecutando.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Procesos concurrentes
• Procesos disjuntos
• Son disjuntos si se ejecutan en diferentes bloques de programa,
sin posibilidad de accederse entre sí. Ambos se ejecutan
simultáneamente y proceden concurrentemente hasta que alguno
o los dos terminan.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Procesos cooperativos
Tienen la necesidad de comunicarse entre sí en la realización de
una tarea, compartiendo recursos en común por lo que requieren
alguna forma de sincronización
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Programación paralela
• Un programa paralelo o distribuido es aquel formado por
varios procesos secuenciales que se ejecutan en varios
procesadores conectados entre sí.
• Si la red se forma por conexiones dentro de una sola
computadora se considera un esquema de
programación paralela.
• Si la red se forma por conexiones entre diferentes
computadoras se considera un esquema de
programación distribuida.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Organización de memoria
• En un sistema multiproceso existen recursos
considerados comunes o compartidos por todos los
procesadores, como son el caso de la memoria y los
medios periféricos.
• La comunicación entre los procesos se clasifica en dos
tipos:
• Fuertemente acoplados
• Para el caso en que el grado de interacción es alto
• Débilmente acoplados
• Para el caso contrario
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Comunicación entre procesos
La manera como la memoria es “repartida” entre los
procesadores determina el MECANISMO DE
COMUNICACIÓN a utilizar:
• Variables compartidas
• En caso de memoria compartida y por lo general procesos
fuertemente acoplados.
• Paso de mensajes
• En caso de memoria distribuida y por lo general procesos
bajamente acoplados.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Memoria compartida
• Un sistema multiproceso con memoria compartida es
aquél que permite el acceso de cualquier procesador del
sistema a cualquier localidad de memoria común.
• Cada dirección es única e idéntica para todo procesador.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
• La comunicación entre procesos se realiza por lectura y
escritura de variables en la misma sección de
memoria.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Memoria
Procesador
1
P
1
P
2
P
3
Memoria compartida
• Para asegurar la integridad de los datos en memoria
compartida son necesarios:
• Mecanismos para el soporte de comunicaciones
• Ambiente de programación que provea la planeación
• Localización
• Sincronización
• Coordinación de procesos.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Memoria distribuida
• Un sistema multiprocesador de memoria
distribuida es aquél en el que cada procesador
utiliza su propia memoria privada.
• La comunicación con otros procesadores mediante
una red de interconexión.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Programación Distribuida
• La comunicación entre procesos se realiza mediante
envío y recepción de datos. Este esquema se conoce
como paso de mensajes.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Conceptos de programación concurrente
y paralela
EXCLUSION MUTUA
• Se refiere a la situación en que dos o más procesos
comunicándose entre sí, mantengan la integridad de
los datos que comparten.
• En el caso de variables compartidas, es la serialización de las
acciones de escritura o lectura sobre una variable.
• En el caso de paso por mensajes se refiere a que cada proceso es
capaz de recibir un solo mensaje a la vez.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Conceptos…
CONDICIÓN DE COMPETENCIA
• Dada la situación de exclusión mutua en la comunicación
entre procesos se hace necesario que los procesos
“compitan” entre sí para tomar posesión de las variables
compartidas, o en caso de paso de mensajes que dos o
más procesos compitan porque su mensaje sea recibido
antes por un tercer proceso.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Conceptos…
JUSTICIA
• Se refiere al hecho de proporcionar la oportunidad a
todos los procesos que ejecuten sus actividades sin que
ninguno quede suspendido o bloqueado
permanentemente.
GRANULARIDAD
• Indica la cantidad de instrucciones a ejecutar que cada
procesador realiza con respecto al tiempo que cada
proceso tarda en comunicarse
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Conceptos…
BALANCE DE TRABAJO
• Para lograr un trabajo eficiente y una distribución
equitativa de procesador(es) es necesario aplicar
técnicas de balance de trabajo para que se distribuyan lo
más uniformemente posibles los procesadores.
• Un balance de trabajo óptimo mantiene los procesadores
ocupados, procurando que todos ellos terminen casi al
mismo tiempo.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Conceptos…
TERMINACION
• Se refiere al hecho de asegurar que todos los procesos
de un programa concurrente finalicen correctamente.
• Si al menos uno de los procesos no termina por alguna
causa, el programa concurrente simplemente no termina
con éxito.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Dead lock
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Abrazo mortal (dead lock)
• Un programa concurrente se encuentra en abrazo mortal
si todos sus procesos se encuentran bloqueados entre sí,
es decir, ninguno puede llegar a terminar
• También existe otro problema llamado inanición, que es
cuando un proceso no puede llegar a ejecutarse, en el
ejemplo de los filósofos que nunca pueda comer ya que
no puede obtener los dos tenedores necesarios.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Si se tiene programación paralela eso significa que
¿se puede dividir el tiempo de procesamiento en el
número de procesadores existentes?
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
P0 P1 P2 P3
P0 P2 P1 P3
P0 P2 P1 P3
Divide y vencerás….
Ley de Amdahl • Propone normalizar el tiempo que toma realizar la operación en un
solo procesador al valor de 1.
• La fracción del cálculo que sólo se puede realizar secuencialmente será F, entonces la fracción paralelizable es1-F.
• Entonces, el incremento de velocidad máximo que puede obtenerse con P elementos de procesamiento está dado por la ecuación:
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
El caso ideal…
• Como un ejemplo, si nuestra aplicación no tiene sección
secuencial , entonces el incremento de velocidad máximo
estará dado exactamente por el número de elementos de
procesamiento:
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Semáforos (Antecedentes)
• En 1968 E.W Dijkstra presentó un artículo “Co-operating
Sequential Process”.
• Realiza una primera propuesta del tratamiento de la concurrencia
en un lenguaje de programación.
• En general al contexto de lenguajes concurrentes.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
¿Para qué los semáforos? • Resuelven el problema de integridad de los datos en un
sistema concurrente cooperativo de variables compartidas.
• Mediante la sincronización de los procesos que lo forman.
• Su representación es:
• Una variable entera positiva
• Las cuáles se afectan únicamente mediante dos primitivas de
ejecución indivisibles:
• V (Verhogen, incrementar)
• P (Proberen, probar )
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Operaciones
• P es operación de un argumento identificado como un semáforo. Su función es decrementar, siempre cuando el valor del decremento no sea negativo.
• V es operación de un argumento identificado como un semáforo. Su función es incrementar.
• Ejemplo: S = 1;
P(S);
x=x+1;
V(S);
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Sección crítica
• Acciones que se realizan sobre las variables compartidas.
• Se puede identificar como la sección que se encuentra
entre P y V de un mismo semáforo.
• La sección crítica, tal como los semáforos figuran en la
primera propuesta de exclusión mutua y sincronización
entre procesos concurrentes.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
• Exclusión mutua con semáforos y secciones críticas
• Seudocódigo:
semaphore S=1;
….
P(S);
N= N+1; // Sección critica(variable compartida)
V(S);
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Sincronización condicional
•El pseudocódigo para sincronización condicial
(disponibilidad de recurso) es:
Semaphore tapeDrives= 7;
//7 procesos dentro de la sección crítica
….
P(tapeDrives);
useTapeDrive();
V(tapeDrives);
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Programación concurrente y semáforos
en Java • En Java es posible ejecutar tareas en paralelo, utilizando
hebras de control (hilos, threads). Este modo de
programación permite tener un espacio de memoria,
código o recursos compartidos. Tiene la ventaja que su
ejecución resulta más económica que un proceso
completo.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Semáforos
• Java cuenta con semáforos implícitos de la forma:
Object mutex = new Object();
/* …*/
Synchonized (mutex){
/* … */
}
Que solo pueden ser utilizados para exclusión mutua.
Solo un hilo de control puede ejecutarse en el bloque synchonized en un momento dado.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Ejemplo del uso de la palabra
Synchonized import java.io.*;
class Banco {
public static void main ( String args[]) {
try {
// Declaramos los dos montones de billetes
Contador co1 = new Contador ();
Contador co2 = new Contador ();
// Declaramos los dos cajeros
Cajero c1 = new Cajero(co1);
Cajero c2 = new Cajero(co2);
// Se ponen a contar..
c1.start();
c2.start();
c1.join();
c2.join();
} catch ( Exception e ){
e.printStackTrace(); }
}
}
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Clase Contador: Cuenta billetes y
almacena la suma class Contador {
int numBilletes = 0 ;
long suma = 0 ;
final int TOTAL_BILLETES = 10000 ;
final int VALOR_BILLETES = 200 ;
void cuenta () {
// A contar la suma de los billetes
for ( numBilletes =0 ; numBilletes < TOTAL_BILLETES;
numBilletes ++ ) {
suma += VALOR_BILLETES ;
// Billetes de 200 pesos Thread.yield(); } System.out.println ( numBilletes+ " suman : "+ suma +
" pesos");
}
}
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Clase Cajero: Recibe cierta cantidad de
billetes para contar class Cajero extends Thread {
Contador contadorCajero ;
Cajero ( Contador paramContador )
{
contadorCajero = paramContador ;
}
public void run ()
{
contadorCajero.cuenta();
}
}
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Resultado:
• 10000 suman 2000000 pesos
• 10000 suman 2000000 pesos
Es correcto, dado que cada cajero tiene su cantidad de
billetes para contar.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Compartiendo el recurso
• Ahora supongamos que los dos cajeros deben contar del mismo montón, o sea, lo comparten y por tanto, la suma de lo que haya contado cada uno debe ser el resultado total.
• Para ello, modificaremos el código añadiendo lo siguiente
Declaramos los dos montones de billetes :
• Contador co1 = new Contador ();
// Ahora sobra, Contador co2 = new Contador ();
// Declaramos los dos cajeros y el mismo montón.
Cajero c1 = new Cajero(co1);
Cajero c2 = new Cajero(co1);
Con este cambio obtenemos:
• 10000 suman: 2000200 pesos
• 10001 suman: 2000200 pesos
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
• El resultado anterior es incorrecto
• Por tanto, debemos utilizar un mecanismo de
sincronización que garantice que cuando un cajero
cuente un billete y lo sume, el otro no pueda intentar
coger el mismo billete y sumarlo. La solución que ofrece
Java para resolver este problema es de lo más simple y
eficiente, utilizando la cláusula synchronized en la
declaración del método donde se realiza la tarea "crítica".
• Por tanto, cambiaremos el método void cuenta() por:
synchronized void cuenta ()
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
• Si realizamos ese cambio, obtenemos el siguiente
resultado:
• 10000 suman : 2000000 pesos
• 10000 suman : 4000000 pesos
• Esto ocurre porque no se inicializa la variable suma antes
del ciclo que cuenta los billetes, por lo que el segundo
cajero continúa la suma en donde la dejó el anterior.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Inicializando el contador • Si modificamos el código e incluimos la inicialización, tendremos:
void cuenta () {
// Cada cajero cuenta lo suyo …
suma = 0 ;
// A contar la suma de los billetes
for ( numBilletes =0 ; numBilletes < TOTAL_BILLETES ;numBilletes ++ )
{
suma += VALOR_BILLETES ;
Thread.yield();
}
}
A partir de este momento obtenemos el siguiente resultado esperado tal y como detallamos:
10000 suman : 2000000 pesos
10000 suman : 2000000 pesos
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
• Otra forma de realizar la sincronización consiste en declarar el objeto compartido como sincronizado en vez del método que lo contiene. Se realiza entonces el siguiente cambio:
public void run(){
contadorCajero.cuenta();
}
por:
public void run(){
synchronized (contadorCajero ) { contadorCajero.cuenta();
}
}
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Monitores
• El siguiente nivel dentro de la solución a los problemas de
exclusión mutua y sincronización entre procesos
concurrentes fue desarrollado por C.A.R. Hoare y P.
Brinch Hansen.
• Ahora se considera como recurso compartido no
únicamente las variables compartidas, sino también a los
procedimientos y funciones que actúan sobre las
variables
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Seudocódigo
• Notación propuesta por Hoare (Simula 67)
monitorname: monitor
begin //declaraciones de datos locales del monitor
procedure //procname { parametros formales }
begin // cuerpo del procedimiento
… // otros procedimiento locales del monitor
end
…
.. //inicialización de los datos locales del monitor
end
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Monitores
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Productor Monitor (recurso
compartido) Consumidor
Ejemplo
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
:TubTest t:Tuberia p:Productor c:Consumidor
new Tuberia()
new Productor(t)
new Consumidor(t)
start( )
start( )
run( )
run( )
lanzar(c )
lanzar(c )
recoger(c )
… …
sleep( )
sleep( )
estaVacia == false
siguiente++
estaLlena==false
siguiente--
estaVacia == false
siguiente++
… …
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
:TubTest t:Tuberia p:Productor c:Consumidor
new Tuberia()
new Productor(t)
new Consumidor(t)
start( )
start( )
run( )
run( )
lanzar(c )
lanzar(c )
recoger(c )
… …
sleep( )
sleep( )
(estaVacia==true)?
estaVacia== false
… …
…
wait()
notify()
estaLlena==false
siguiente--
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Lectura y Escritura de Archivos
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class LecturaEscrituraArchivos {
public static void main(String args[]){
copiaArchivo("c:/archivoEntrada.txt", "c:/archivoSalida.txt");
}
•
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
public static void copiaArchivo (String archivoLectura, String archivoEscritura){
try{
FileInputStream fileInput = new FileInputStream(archivoLectura);
BufferedInputStream bufferedInput = new BufferedInputStream(fileInput);
FileOutputStream fileOutput = new FileOutputStream(archivoEscritura);
BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutput);
byte [] array = new byte [1];
int leidos= bufferedInput.read(array);
while(leidos > 0){
bufferedOutput.write(array);
leidos=bufferedInput.read(array);
}
bufferedInput.close();
bufferedOutput.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
RandomAccessFile
• Mediante los objetos de esta clase utilizamos archivos
binarios mediante un acceso aleatorio, tanto para lectura
como para escritura.
• Existe un índice que nos indica en qué posición del
archivo nos encontramos, y con el que se puede trabajar
para posicionarse en el archivo.
• RandomAccessFile(String nombre, String modo)
• nombre: cadena identificadora del archivo
• modo: si será de lectura y/o escritura
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Ejemplo de algunos métodos de escritura
• La escritura del archivo se realiza con una función que depende el tipo de datos que se desee escribir.
• void write( byte b[], int ini, int len ); Escribe len caracteres del vector b.
• void write( int i ); Escribe la parte baja de i (un byte) en el flujo.
• void writeBoolean( boolean b ); Escribe el boolean b como un byte.
• void writeByte( int i ); Escribe i como un byte.
• void writeBytes( String s ); Escribe la cadena s tratada como bytes, no caracteres.
• void writeChar( int i ); Escribe i como 1 byte.
• void writeChars( String s ); Escribe la cadena s.
• void writeDouble( double d ); Convierte d a long y le escribe como 8 bytes.
• void writeFloat( float f ); Convierte f a entero y le escribe como 4 bytes.
• void writeInt( int i ); Escribe i como 4 bytes.
• void writeLong( long v ); Escribe v como 8 bytes.
• void writeShort( int i ); Escribe i como 2 bytes.
• void writeUTF( String s ); Escribe la cadenas UTF
• Para la lectura existen métodos análogos para leer cada uno de los tipos de datos.
Arquitecturas Cliente/Servidor, Sem 2016-1
M.I.Yasmine Macedo Reza
Top Related