{ "version": "2", "formats": { "markdown": { "content": "## Page 1\n\nUnidad 1\nProgramación concurrente\n\nTema 2 Exclusión\n\n<page_number>1</page_number>\n\n---\n\n\n## Page 2\n\n# Contenidos\n\n1. Exclusión\n2. Inmutabilidad\n * Aplicaciones\n * Construcción\n3. Sincronización\n * Formas de conseguir sincronización\n * Objetos completamente sincronizados\n * Estrategias de recorrido en colecciones\n4. Confinamiento\n * Singleton\n * Interbloqueo\n * Atomicidad\n * A través de métodos\n * Dentro de hilos\n * De objetos\n * De grupos\n* Bibliografía\n\n<page_number>2</page_number>\n\n---\n\n\n## Page 3\n\n# Exclusión\n\n* En un sistema seguro\n Cada objeto se protege contra las violaciones de integridad\n* Las técnicas de exclusión...\n Preservan los invariantes del objeto y evitan los efectos que resultarían de actuar momentáneamente sobre representaciones de estados incoherentes\n Evitan que múltiples hilos modifiquen o actualicen concurrentemente representaciones de objetos\n\n<page_number>3</page_number>\n\n---\n\n\n## Page 4\n\n# Exclusión\n\n* Tres estrategias para garantizar la exclusión\n * Eliminar la necesidad de exclusión (parcial o total)\n * Asegurar que los métodos nunca modifiquen la representación de un objeto\n * Nunca habrá estados incoherentes\n * Asegurar dinámicamente que sólo un hilo **pueda acceder** a la vez al estado del objeto\n * Protección del objeto con cerrojos\n * Asegurar estructuralmente que sólo un hilo **pueda usar** un objeto dado\n * Ocultación o restricción de acceso al mismo\n* La combinación de estas estrategias pueden mejorar\n * Seguridad, vivacidad y rendimiento\n\n<page_number>4</page_number>\n\n---\n\n\n## Page 5\n\n# Exclusión\n\n* Los programas concurrentes son menos tolerantes a fallos\n* La seguridad no se puede conseguir\n * Con el compilador\n * Comprobación estática de tipos\n * En tiempo de ejecución\n * Pruebas funcionales - para un conjunto de entradas comparar la salida esperada con la salida deseada\n* La responsabilidad recae en los programadores\n * Las estrategias de exclusión y reglas de diseño deben ser explícitas y visibles\n* Tener precaución al utilizar código no diseñado para ejecutarse en contextos concurrentes\n * Utilizar envolturas (PD Adaptador)\n\n<page_number>5</page_number>\n\n---\n\n\n## Page 6\n\n# Inmutabilidad\n\n* **Intención**\n * Si un objeto nunca puede cambiar de estado entonces nunca se encontrará en conflictos o inconsistencias cuando múltiples actividades intenten cambiar de estado de forma incompatible\n* No siempre se puede aplicar pero un uso selectivo de la inmutabilidad es una herramienta básica de la programación concurrente\n* ¿Cómo conseguir objetos inmutables?\n * Independientes del estado - no tienen ningún campo interno\n * Clases que sólo poseen campos final\n\n<page_number>6</page_number>\n\n---\n\n\n## Page 7\n\n# Inmutabilidad\n\n* Las instancias de clases inmutables no pueden tener conflictos de lectura/escritura o escritura/escritura\n* No pueden experimentar fallos de invariantes\n\n```java\nclass SumadorSinEstado {\n public int sumar(int a, int b) { return a + b; }\n}\n```\n☑️ V\n\n```java\nclass SumadorInmutable {\n private final int incremento;\n\n public SumadorInmutable(int a) { incremento = a; }\n\n public int sumaIncremento(int b) { return incremento + b; }\n}\n```\n☑️ V\n\n---\n\n\n## Page 8\n\n# Inmutabilidad – Aplicaciones\n\n* Contenedores de valores\n * java.awt.Color\n * java.lang.Integer\n * java.lang.String\n* Otros tipos que se pueden diseñar como inmutables\n\n1. Las instancias de las clases nunca alteran los valores de sus campos pero pueden proporcionar métodos que crean objetos para representar nuevos valores\n2. La identidad de los objetos inmutables no importa\n * Redefinir los métodos equals() y hashCode() que se heredan de Object\n * Fraccion, Intervalo, ComplexFloat\n\n<page_number>8</page_number>\n\n---\n\n\n## Page 9\n\n# Inmutabilidad – Aplicaciones\n\n```java\nclass Fraccion {\n protected final long numerador;\n protected final long denominador;\n\n public Fraccion(long num, long den) {\n // normalización\n boolean igualSigno = (num >= 0) == (den >= 0);\n long n = (num >= 0) ? num : -num;\n long d = (den >= 0) ? den : -den;\n long g = mcd(n, d);\n numerador = (igualSigno) ? n / g : -n / g;\n denominador = d / g;\n }\n\n static long mcd(long a, long b) {\n // ... calculo del máximo común divisor ...\n return 1;\n }\n\n public Fraccion suma(Fraccion f) {\n return new Fraccion(numerador * f.denominador +\n f.numerador * denominador,\n denominador * f.denominador);\n }\n\n public boolean equals(Object other) { // redefinición\n if (!(other instanceof Fraccion)) return false;\n Fraccion f = (Fraccion)(other);\n return numerador * f.denominador ==\n denominador * f.numerador;\n }\n\n public int hashCode() { // redefinición\n return (int) (numerador ^ denominador);\n }\n}\n```\n\n<img>Green circle with white check mark</img> <img>Blue circle with white V</img>\n<page_number>9</page_number>\n\n---\n\n\n## Page 10\n\n# Inmutabilidad – Aplicaciones\n\n* Tipos abstractos de datos (TDAs)\n * No siempre hay que hacer solo representaciones inmutables\n * String vs. StringBuffer (modificable a través de métodos sincronizados)\n* Contenedores de valores\n * Cuando se necesita establecer un estado coherente y depender de él para siempre\n * Ejemplo ProgramConfiguration\n* Crear nuevos objetos mediante copia deben ser relativamente inusuales o baratas\n* Compartición -PD Flyweight-\n * Es útil cuando se quieren compartir objetos por eficiencia de espacio\n * Ej1: Instancias de uso general\n * Ej2: Caracteres comparten formato\n\n```java\nclass Retransmitir {\n protected final Server servidor;\n Retransmitir(Server s) { servidor = s; }\n void doIt() { servidor.doIt(); }\n}\n\n---\n\n\n## Page 11\n\n# Inmutabilidad – Construcción\n\n* Uso apropiado de la palabra clave final\n* Precaución al inicializar objetos inmutables\n\n**NO PERMITIR QUE LOS CAMPOS SEAN ACCESIBLES HASTA QUE LA CONSTRUCCIÓN DEL OBJETO SE COMPLETE**\n\n* Los constructores\n * No deben invocar ningún método cuyos efectos dependan del objeto está siendo construido\n * Deben evitar almacenar una referencia a un objeto que se haya construido con campos o tablas accesibles por otros, evitando hacer llamadas con `this` como argumento\n* Si la construcción del objeto se inicializa incrementalmente desde archivo o interdependencias entre distintos objetos que se construyan al mismo tiempo → Suele implicar sincronización\n\n<page_number>11</page_number>\n\n---\n\n\n## Page 12\n\n# Sincronización\n\n* Los bloqueos nos protegen contra conflictos de almacenamiento de bajo nivel y los correspondientes fallos de invariantes de alto nivel\n* Violación de la **postcondición**\n * Suelen ser raras y difícil de comprobar pero pueden tener **efectos devastadores**\n\n```mermaid\nsequenceDiagram\n participant Hilo A\n participant Hilo B\n Hilo A -> Hilo B: Lee 0\n Hilo A -> Hilo B: Escribe 1\n Hilo B -> Hilo A: Lee 1\n Hilo B -> Hilo A: Escribe 2\n Hilo A -> Hilo B: Lee 2\n Hilo B -> Hilo A: Escribe 3\n Hilo A -> Hilo B: Escribe 3\n Hilo B -> Hilo A: Retorna 3\n```\n\n//Ejemplo docente no usar\nclass Par {\n private int n = 0;\n public int siguiente(){\n ++n;\n ++n;\n //POST: n es siempre par\n //INV: n es siempre par\n assert n % 2 == 0 : \"INV:\";\n return n;\n }\n}\n\n---\n\n\n## Page 13\n\n# Sincronización\n\n* Si se declara el método `Par.siguiente()` como **synchronized** se evitan los conflictos\n* El bloqueo provoca la ejecución en serie de los métodos sincronizados\n\n\ngraph TD\n subgraph Hilo A coge cerrojo\n A1[Lee 0]\n A2[Escribe 1]\n A3[Lee 1]\n A4[Escribe 2]\n A5[Retorna 2]\n end\n\n subgraph Hilo B\n B1[se bloquea]\n B2[...]\n B3[Retorna 4]\n end\n\n A1 --> A2\n A2 --> A3\n A3 --> A4\n A4 --> A5\n\n B1 --> B2\n B2 --> B3\n\n A5 --> B3\n B3 --> A1\n\n\ntiempo\n\n```java\nclass Par {\n private int n = 0;\n public synchronized int siguiente(){\n ++n;\n ++n;\n //POST: n es siempre par\n //INV: n es siempre par\n assert n % 2 == 0 : \"INV: n es par\";\n return n;\n }\n}\n```\n\n<img>Green check mark icon</img> <img>Blue V icon</img>\n\n<page_number>13</page_number>\n\n---\n\n\n## Page 14\n\n# Sincronización\n\n## Formas de conseguir la sincronización\n\n* **Objetos y cerrojos**\n * Cada instancia de la clase `Object` y de sus subclases poseen un cerrojo\n * Los tipos primitivos `int`, `float`... no son objetos\n* Los campos individuales no se pueden marcar con `synchronized`\n* El bloqueo sólo se puede aplicar al uso de campos dentro de métodos\n* El bloqueo de un array de `Objects` no bloquea sus elementos\n* Los cerrojos asociados con métodos con alcance de clase utilizan `synchronized static`\n\n<page_number>14</page_number>\n\n---\n\n\n## Page 15\n\n# Sincronización\n\n## Formas de conseguir la sincronización\n\n* Métodos y bloques sincronizados\n * Dos construcciones sintácticas basada en la palabra clave **synchronized**\n 1. Bloques\n * Toma como argumento el objeto que bloquea\n * Argumento común **this**\n\n```java\n// Sincronización método\nsynchronized void f(){/*Cuerpo método*/}\n// Sincronización de bloque equivalente\nvoid f(){synchronized (this){/*Cuerpo método*/}}\n\n---\n\n\n## Page 16\n\n# Sincronización\n## Formas de conseguir la sincronización\n\n### 2. Métodos sincronizados\n* `synchronized` no forma parte de la signatura del método\n* **Herencia**\n * No se hereda la sincronización\n * La interface de Java no pueden tener métodos `synchronized`\n * Los métodos de instancia de la subclase emplean el mismo cerrojo que su superclase\n* **Constructores**\n * Los constructores no pueden ser `synchronized` aunque si pueden contener bloques `synchronized`\n\n6\n\n---\n\n\n## Page 17\n\n# Sincronización\n\n## Formas de conseguir la sincronización\n\n### 2. Métodos sincronizados\n\n* Clases internas y externas\n * La sincronización de un método de clase interno es independiente de su clase externa\n * Un método interno no estático de la clase interna puede bloquear la clase que la contiene mediante el uso de bloques de código\n\n```java\npublic class ClaseExterna {\n private class ClassIntena {\n public void f() {\n synchronized (ClaseExterna.this) {\n /* Cuerpo método */\n }\n }\n }\n}\n```\n\n<img>V logo</img>\n<page_number>17</page_number>\n\n---\n\n\n## Page 18\n\n# Sincronización\n\n## Formas de conseguir la sincronización\n\n* **Adquisición y liberación de cerrojos**\n * Protocolo de adquisición y liberación definido con la palabra reservada `synchronized`\n * Un cerrojo\n - Se **adquiere** a la entrada del método o bloque `synchronized`\n - Se **libera** a la salida, incluso si se termina con el lanzamiento de una excepción\n * Los cerrojos funcionan en el contexto de hilos y no en la invocación de métodos\n - Un hilo avanza por un método `synchronized` si el **cerrojo** está libre o el hilo posee ya el cerrojo\n - En otro caso el hilo se bloquea (bloqueo reentrante)\n\n<page_number>18</page_number>\n\n---\n\n\n## Page 19\n\n# Sincronización\n\n## Formas de conseguir la sincronización\n\n* **Adquisición y liberación de cerrojos**\n * El bloqueo reentrante se diferencia de la política usada por defecto por hilos POSIX\n * Un método `synchronized` puede hacer una llamada a otro método `synchronized` del mismo objeto sin que se paralice\n * En otro caso el hilo se bloquea (bloqueo reentrante)\n * Un método o bloque `synchronized` se corresponde con un protocolo de adquisición y liberación de cerrojos con respecto a otros métodos `synchronized` y bloques del mismo objeto destino\n * Los métodos `no synchronized` pueden ejecutarse en cualquier momento incluso si un método `synchronized` se está ejecutando\n\n<page_number>19</page_number>\n\n---\n\n\n## Page 20\n\n# Sincronización\n\n## Formas de conseguir la sincronización\n\n* **Adquisición y liberación de cerrojos**\n * Cuando un hilo libera un cerrojo, otro hilo puede adquirirlo\n * No hay garantía cuál de los hilos bloqueados adquirirá el cerrojo\n * No hay mecanismo para descubrir si un cerrojo fue adquirido por algún hilo\n* **Miembros estáticos**\n * El bloqueo de un objeto no protege automáticamente los campos static de la clase o sus superclases\n * El acceso a los campos static se protege mediante métodos y bloques synchronized static\n * Se emplea el cerrojo que posee el objeto Class asociado con la clase en la que se declaran los método estáticos\n\n<page_number>20</page_number>\n\n---\n\n\n## Page 21\n\n# Sincronización\n## Formas de conseguir la sincronización\n\n* **Miembros estáticos**\n * El cerrojo `static` sobre C se puede alcanzar desde métodos de instancia\n - `synchronized (C.class) { /* cuerpo */ }`\n * El cerrojo estático de cada clase no está asociado con el de otra clase incluyendo su superclase\n - No es eficaz agregar un método `synchronized static` en una subclase que intente proteger los campos `static` declarados en la superclase\n - Se considera mala práctica usar estructuras de la forma\n * `synchronized (getClass()) { /* cuerpo */ }`\n * JVM adquiere y libera internamente los cerrojos de la Class durante la carga y la inicialización de la clase\n\n<page_number>21</page_number>\n\n---\n\n\n## Page 22\n\n# Sincronización\n\n## Objetos completamente sincronizados\n\n* Los cerrojos se pueden utilizar para bloquear a los clientes que intenten invocar un método de un objeto mientras que otro método o bloque de código está ejecutando dicho método\n\n\ngraph TD\n subgraph Cliente\n A[cliente]\n end\n\n subgraph Objeto\n B[Estado del objeto]\n C[accion (){ ... }]\n D[cerrojo]\n end\n\n A --> D\n D --> B\n D --> C\n C --> B\n\n\n<page_number>22</page_number>\n\n---\n\n\n## Page 23\n\n# Sincronización\n\n## Objetos completamente sincronizados\n\n* La estrategia **más segura** de diseño concurrente es utilizar objetos completamente sincronizados o atómicos\n * Todos los método son **synchronized**\n * No hay campos públicos o violaciones de encapsulación\n * Todos los métodos son finitos\n * No contienen bucles infinitos ni recursión infinita\n * El cerrojo se libera alguna vez\n * Todos los campos se inicializan a un estado consistente en los constructores\n * El estado del objeto es consistente (cumple invariantes)\n * Al principio y al final de cada método,\n * Incluso con la presencia de excepciones\n\n<page_number>23</page_number>\n\n---\n\n\n## Page 24\n\n# Sincronización\n\n## Objetos completamente sincronizados\n\n```java\npublic class ExpandableArray {\n protected Object[] data; // the elements\n protected int size = 0; // the number of array slots used\n // INV: 0 <= size <= data.length\n\n public ExpandableArray(int cap) {\n data = new Object[cap];\n }\n\n public synchronized int size() {\n return size;\n }\n\n public synchronized Object get(int i) // subscripted access\n throws NoSuchElementException {\n if (i < 0 || i >= size)\n throw new NoSuchElementException();\n return data[i];\n }\n}\n```\n<img>Green circle with white check mark icon</img>\n<page_number>24</page_number>\n\n---\n\n\n## Page 25\n\n# Sincronización\n\n## Objetos completamente sincronizados\n\n```java\npublic class ExpandableArray {\n //...\n public synchronized void add(Object x) { // add at end\n if (size == data.length) { // need a bigger array\n Object[] olddata = data;\n data = new Object[3 * (size + 1) / 2];\n System.arraycopy(olddata, 0, data, 0, olddata.length);\n }\n data[size++] = x;\n }\n public synchronized void removeLast() throws NoSuchElementException {\n if (size == 0)\n throw new NoSuchElementException();\n data[--size] = null;\n }\n}\n```\n\n* No tiene conflictos lectura/escritura\n * get () en mitad de ejecución `removeLast ()`\n* Se eliminan conflictos escritura/escritura\n * Se ejecutan concurrentemente dos `add ()`\n\n<page_number>25</page_number>\n\n---\n\n\n## Page 26\n\n# Sincronización\n\n## Estrategias de recorridos en colecciones\n\n* 1 .Con bloqueo en el lado del cliente\n * API `java.util.Collections`\n * Utiliza un wrapper (PD Decorador) para obtener una colección completamente sincronizada\n * Añade muchos métodos de envoltura del tipo\n * `public static Collection synchronizedCollection(Collection c)`\n * Devuelve una colección sincronizada (segura en contextos de hilos) a partir de la colección especificada. Con el fin de garantizar el acceso secuencial\n * El usuario es el encargado de sincronizar los recorridos\n\n```java\nCollection c = Collections.synchronizedCollection(myCollection);\n\n...\n\nsynchronized (c) {\n Iterator i = c.iterator(); // Must be in the synchronized block\n while (i.hasNext())\n foo(i.next());\n}\n```\n\n<img>Green checkmark icon</img> <img>Blue V icon</img>\n<page_number>26</page_number>\n\n---\n\n\n## Page 27\n\n# Sincronización\n\n## Estrategias de recorridos en colecciones\n\n* 2. Operaciones sincronizadas agregadas en la colección\n * Se puede asegurar el recorrido si:\n 1. Se abstrae la función que se quiere aplicar a cada elemento de la colección\n 2. Se define un método sincronizado en la colección\n\n```java\n1 interface Procedure {\nvoid apply(Object obj);\n}\n\nclass ExpandableArrayWithApply extends ExpandableArray {\n\npublic ExpandableArrayWithApply(int cap) { super(cap); }\n\n2 synchronized void applyToAll(Procedure p) {\nfor (int i = 0; i < size; ++i)\np.apply(data[i]);\n}\n}\n```\n<img>Green circle with white check mark</img>\n<page_number>27</page_number>\n\n---\n\n\n## Page 28\n\n# Sincronización\n\n## Estrategias de recorridos en colecciones\n\n* 3. Iteradores con control de versiones\n * Lanzan una excepción si la colección se modifica a mitad de recorrido\n * Una forma de implementarlo\n * Mantener un número de versión que se incrementa en cada actualización de la colección\n * El iterador puede comprobar ese valor siempre que se pida el elemento siguiente y lanza una excepción si ha cambiado\n * Esta estrategia se utiliza en las clases que implementan\n * java.util.Iterator\n * Lanzan una excepción en tiempo de ejecución\n * ConcurrentModificationException\n\n<page_number>28</page_number>\n\n---\n\n\n## Page 29\n\n# Sincronización Singleton\n\n* **Intención**\n * Garantiza que una clase solo tenga una instancia, y proporciona un punto de acceso global a ella\n* **Solución no concurrente**\n * La clase **Singleton** define una variable estática que referencia a la única instancia de la clase\n * Para prevenir que los clientes creen más instancias de la clase se declara el **constructor privado**\n * Para permitir el acceso a la instancia, la clase proporciona un método **estático**, típicamente llamado **getInstance()**\n\n```mermaid\nclassDiagram\n class Singleton {\n - <> Singleton()\n + getInstance(): Singleton\n }\n Singleton --|> Singleton : - instance\n```\n\n<img>Red circle with a white cross</img>\n<page_number>29</page_number>\n\n---\n\n\n## Page 30\n\n# Sincronización Singleton\n\n* En concurrencia dos hilos distintos pueden invocar al método getInstance() en el mismo instante de tiempo\n* Solución concurrente 1\n\n1. Evitar inicialización retardada\n2. Sincronizar completamente el objeto\n\n```java\nclass EagerSingletonCounter {\n private final long initial;\n private long count;\n private EagerSingletonCounter() {\n initial = Math.abs(new java.util.Random().nextLong() / 2);\n count = initial;\n }\n private static final EagerSingletonCounter s = new EagerSingletonCounter();\n public static EagerSingletonCounter instance() { return s; }\n public synchronized long next() { return count++; }\n public synchronized void reset() { count = initial; }\n}\n```\n<page_number>30</page_number>\n\n---\n\n\n## Page 31\n\n# Sincronización Singleton\n\n* Solución concurrente 2\n\n\ngraph LR\n A[1] --> B[Bloqueo de clase en la inicialización de la instancia]\n A[2] --> C[Bloqueos de clase en el cuerpo de los métodos]\n\n\n```java\nprivate LazySingletonCounter() {\n initial = Math.abs(new java.util.Random().nextLong() / 2);\n count = initial;\n}\n\nprivate static LazySingletonCounter s = null;\nprivate static final Object classLock =\n LazySingletonCounter.class;\n\npublic static LazySingletonCounter instance() {\n synchronized(classLock) {\n if (s == null)\n s = new LazySingletonCounter();\n return s;\n }\n}\n\npublic long next() {\n synchronized(classLock) { return count++; }\n}\n\npublic void reset() {\n synchronized(classLock) { count = initial; }\n}\n```\n\n<img>Green circle with white check mark</img>\n<page_number>31</page_number>\n\n---\n\n\n## Page 32\n\n# Sincronización Singleton\n\n* Solución concurrente 3\n * Si no hay necesidad de depender de las instancias\n * Utilizar todos los métodos estáticos sincronizados\n * No hace falta constructor para crear instancias\n\n```java\nclass StaticCounter {\n private static final long initial =\n Math.abs(new java.util.Random().nextLong() / 2);\n private static long count = initial;\n private StaticCounter() { } // disable instance construction\n public static synchronized long next() { return count++; }\n public static synchronized void reset() { count = initial; }\n}\n```\n<img>Green checkmark icon</img>\n\n<page_number>32</page_number>\n\n---\n\n\n## Page 33\n\n# Sincronización\n## Interbloqueo\n\n* Seguridad vs. Vivacidad\n * Los objetos atómicos son siempre seguros pero los hilos que lo usan no están siempre activos\n* Ejemplo interbloqueo: Celda.intercambiarValor adquiere cerrojos en múltiples objetos (t, otro)\n\n```java\nclass Celda { // No usar\n private long valor;\n synchronized long getValor() { return valor; }\n synchronized void setValor(long v) { valor = v; }\n\n synchronized void intercambiarValor(Celda otro) {\n long t = getValor();\n long v = otro.getValor();\n setValor(v);\n otro.setValor(t);\n }\n}\n```\n<img>Red circle with white X</img>\n<page_number>33</page_number>\n\n---\n\n\n## Page 34\n\n# Sincronización\n## Interbloqueo\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Hilo 1 (a.intecambiarValor(b))Hilo 2 (b.intecambiarValor(a))
1 Adquiere el cerrojo sobre a al entrar en a.intercambiarValor
Adquiere el cerrojo sobre b al entrar en b.intercambiarValor
2 No se bloquea en el cerrojo de a pues ya lo posee al entrar en t = getValor()No se bloquea en el cerrojo de b pues ya lo posee al entrar en t = getValor()
3 Se bloquea esperando a tomar el cerrojo sobre b para entrar en v = b.getValor()Se bloquea esperando a tomar el cerrojo sobre a para entrar en v = a.getValor()
4
\n\nHilo 1\n<img>A diagram showing two threads (Hilo 1 and Hilo 2) interacting with two locks (cerrojo a and cerrojo b). The arrows indicate that thread 1 acquires lock a, then tries to acquire lock b, and thread 2 acquires lock b, then tries to acquire lock a.</img>\n<page_number>34</page_number>\n\n---\n\n\n## Page 35\n\n# Sincronización\n\nInterbloqueo – ordenación de recursos\n\n* Una técnica sencilla de evitar el interbloqueo\n * Ordenación de recursos\n * Asociar una etiqueta numérica a cada objeto que se pueda bloquear en un bloque o método `synchronized`\n * Alternativa para etiquetar `System.identifyHashCode(Object o)`\n * 1 - Si la sincronización siempre se realiza del de menor orden con respecto a las etiquetas nunca se da el interbloqueo\n * 2 - Se debe comprobar la detección del alias\n * Dos o más referencias se asignan al mismo objeto\n<page_number>35</page_number>\n\n---\n\n\n## Page 36\n\n# Sincronización\n\n## Interbloqueo – ordenación de recursos\n\n```java\npublic class Celda {\n private long valor;\n\n synchronized long getValor() {\n return valor;\n }\n\n synchronized void setValor(long v) {\n valor = v;\n }\n\n public void intercambiarValor(Celda otra) {\n // 2\n if (otra == this)\n return;\n // 1\n else if (System.identityHashCode(this) < System.identityHashCode(otra))\n this.hacerIntercambiarValor(otra);\n else\n otra.hacerIntercambiarValor(this);\n }\n\n protected synchronized void hacerIntercambiarValor(Celda otra) {\n // Igual version original\n long t = getValor();\n long v = otra.getValor();\n setValor(v);\n otra.setValor(t);\n }\n}\n```\n\n<img>Green checkmark icon</img>\n<page_number>36</page_number>\n\n---\n\n\n## Page 37\n\n# Sincronización Atomicidad\n\n## Instrucciones que deben tener efectos indivisibles\n\n* El modelo de memoria Java\n * Permite lecturas y escrituras atómicas de celdas de memoria\n * Cualquier tipo primitivo excepto (long o double) tiene garantizada la atomicidad\n * volatile extiende la atomicidad a referencias a objetos y tipos primitivos long y double\n* La atomicidad no elimina la necesidad de sincronizar acciones atómicas\n\n```java\npublic final class VFloat{\n private float valor;\n final synchronized void set(float f){valor = f;}\n final synchronized float get(){return valor;}\n}\n// Equivalente\nvolatile float;\n```\n\n<img>V logo</img>\n<page_number>37</page_number>\n\n---\n\n\n## Page 38\n\n# Sincronización Atomicidad\n\n* La atomicidad no elimina la necesidad de sincronizar acciones atómicas\n * La declaración de campos volatile tiene menos coste que la sincronización\n * Adecuado cuando no hay razón para necesitar bloqueos y los valores deben ser accesibles con exactitud por múltiples hilos\n * Termómetro declarar temperatura volatile\n * El campo no necesita cumplir ningún invariante con respecto a otros\n * La escritura del campo no depende de su valor actual\n * Ningún hilo escribe nunca ningún valor ilegal respecto a su semántica\n * Las acciones de los lectores no dependen de valores de otros campos no volatiles\n\n<page_number>38</page_number>\n\n---\n\n\n## Page 39\n\n# Sincronización Atomicidad\n\n* Variables atómicas en Java vs sincronización\n\n```java\npublic class ContadorNoSincronizado {\n private int c = 0;\n\n //Evaluación de expresión no es atómica\n public void increment() { c++; }\n //Evaluación de expresión no es atómica\n public void decrement() { c--; }\n public int value() { return c; }\n}\n```\n<img>Red circle with white cross</img>\n\n```java\nclass ContadorSincronizado {\n private int c = 0;\n\n public synchronized void increment() { c++; }\n public synchronized void decrement() { c--; }\n public synchronized int value() { return c; }\n}\n```\n<img>Green circle with white check mark</img>\n\n```java\nimport java.util.concurrent.atomic.AtomicInteger;\nclass ContadorAtomico {\n private AtomicInteger c = new AtomicInteger(0);\n\n public void increment() {\n c.incrementAndGet();\n }\n public void decrement() {\n c.decrementAndGet();\n }\n public int value() {\n return c.get();\n }\n}\n```\n<img>Red arrow pointing right</img>\nMenor sobrecarga que la sincronización\n<img>Green circle with white check mark</img>\n<page_number>39</page_number>\n\n---\n\n\n## Page 40\n\n# Confinamiento\n\n* Emplear técnicas de encapsulamiento para garantizar estructuralmente que como mucho, una actividad puede acceder a un objeto determinado\n * Elimina la necesidad de bloqueos dinámicos\n* La táctica es definir métodos y clases que establecen dominios de propiedad herméticos que garantizan que un hilo o un hilo a la vez puede tener acceso a un objeto confinado\n\n\ngraph TD\n subgraph \" \"\n A[ ] -- \"Objetos\" --> B[ ]\n C[ ] -- \"Actividades\" --> D[ ]\n E[ ] -- \"Conexiones entre objetos\" --> F[ ]\n end\n\n\n<page_number>40</page_number>\n\n---\n\n\n## Page 41\n\n# Confinamiento\n\n* El confinamiento depende de:\n * Ámbito, control de acceso y características del lenguaje respecto la ocultación de datos y encapsulamiento\n* Instantes en las que una referencia **r** a un objeto **x** se puede escapar de un método **m** que ejecuta una actividad\n * **m** pasa **r** como argumento en la invocación de un método o en el constructor de un objeto\n * **m** pasa **r** como valor de retorno de la invocación de un método\n * **m** almacena **r** en algún campo que sea accesible desde otra actividad\n * **m** libera (de cualquiera de las maneras mencionadas) otra referencia que se pueda utilizar alternativamente para tener acceso a **r**\n\n<page_number>41</page_number>\n\n---\n\n\n## Page 42\n\n# Confinamiento\n\n* **Tipos de confinamiento**\n * **Confinamiento de métodos**\n * Implica práctica de programación ordinaria que tienen que ver con variables locales\n * **Confinamiento de hilos**\n * Técnicas para restringir el acceso dentro de hilos\n * **Confinamiento de objetos**\n * Técnicas de encapsulamiento OO para asegurar la unicidad de acceso para los métodos que incorporan objetos\n * **Confinamiento de grupo**\n * Amplia las técnicas a los conjuntos de colaboración de objetos que operan a través de múltiples hilos\n\n<page_number>42</page_number>\n\n---\n\n\n## Page 43\n\n# Confinamiento de métodos\n\nSi una invocación de un método crea un objeto y no lo deja escapar, entonces se puede asegurar que ningún otro hilo interferirá con el uso de ese objeto\n\n* Es una ocultación dentro de ámbitos locales\n* La técnica se puede extender en las secuencias de invocaciones del método\n\n* Llamada a final del método es un protocolo sin intervención explícita\n * Asegura que en un momento dado como máximo puede tener acceso a un objeto un único método que se ejecuta activamente\n * Uso métodos de fabricación (PD Factory method)\n * Ejemplo: `AppletParticula.crearHilo()`\n\n<page_number>43</page_number>\n\n---\n\n\n## Page 44\n\n# Confinamiento de métodos\n## Sesiones\n\n1. Un cierto método público de entrada construye los objetos que serán confinados en una secuencia de operaciones que comprenden un servicio\n2. El método de entrada también es responsable de las operaciones de limpieza en general\n\n```java\npublic class SessionBasedService {\n public void service() {\n OutputStream output = null;\n try {\n output = new FileOutputStream(\"...\");\n // llamada a final de método\n doService(output);\n } catch (IOException e) {\n handleIOFailure();\n } finally {\n try {\n if (output != null)\n output.close();\n } catch (IOException ignore) {} // ignorar la excepción de cierre\n }\n }\n\n void handleIOFailure() {\n\n }\n\n void doService(OutputStream s) throws IOException {\n s.write(0);\n // ... más instrucciones sin control manual\n }\n}\n```\n\n<img>Blue Checkmark Icon</img> <img>Green Checkmark Icon</img>\n<page_number>44</page_number>\n\n---\n\n\n## Page 45\n\n# Confinamiento de métodos\n## Protocolos alternativos\n\n* Si un método debe tener acceso a un objeto después de una llamada o debe hacer llamadas múltiples no puede aplicarse el protocolo **llamada a final de método**\n\n1.- Copia en el llamador\n```java\nmuestra(new Point(p.x, p.y));\n```\n<img>Green check mark icon</img>\n\n2.- Copias en el receptor\n```java\nprotected void muestra(Point p) {\n //primera línea del receptor\n Point puntoLocal = new Point(p.x, p.y);\n // ...algun forma de mostrar p\n}\n```\n<img>Green check mark icon</img>\n\n```java\npublic class TrazadorGrafico {\n public void muestraSiguientePunto() {\n Point p = new Point();\n p.x = calculaX();\n p.y = calculaY();\n muestra(p);\n /*Se necesita protocolos alternativos\n *a la llamada a final de método*/\n guardaDistancia(p);\n }\n}\n```\n<img>Red cross icon</img>\n\n3.- Uso de argumentos escalares\n```java\nmuestra(p.x, p.y);\nprotected void muestra(int coordx, int coordy){ }\n```\n<img>Green check mark icon</img>\n\n4.- Confianza Un receptor (o mejor su autor) se compromete a no modificar o trasmitir el objeto\n\n<page_number>45</page_number>\n\n---\n\n\n## Page 46\n\n# Confinamiento dentro de hilos\n\nLas técnicas se pueden extender de las secuencias de método. Técnica sencilla usar un hilo por sesión (idéntico al confinamiento basado en sesiones *)\n\n```java\nclass ThreadPerSessionBasedService {\n public void service() {\n Runnable r = new Runnable() {\n public void run() {\n OutputStream output = null;\n try {\n output = new FileOutputStream(\"....\");\n doService(output);\n } catch (IOException e) {\n handleIOFailure();\n }\n finally {\n try { if (output != null) output.close(); } catch (IOException ignore) {}\n }\n }\n };\n new Thread(r).start();\n }\n\n void handleIOFailure() {}\n void doService(OutputStream s) throws IOException {\n s.write(0);\n // ... possibly more hand-offs ...\n }\n}\n```\n\n<img>V logo</img> <img>Green circle with white checkmark</img>\n<page_number>46</page_number>\n\n---\n\n\n## Page 47\n\n# Confinamiento dentro de hilos\n\n* Alternativas de diseño concurrentes para el confinamiento de datos dentro de hilos\n 1. Requerir que todos los campos que son accesibles dentro del hilo estén estrictamente confinados en ese hilo\n * CSP y procesos\n 2. En JVM se comparten accesos de los recursos subyacentes\n * java.lang.System;\n* Como confinar campos específicos dentro los hilos\n 1. Recibir referencias confinadas a lo largo de secuencia de llamadas\n 2. Extender de la clase Thread\n a) Añadir campos específicos\n b) Añadir métodos para acceder a los campos del hilo actual\n * La secuencia de métodos que se ejecutan en el hilo pueden tener acceso al objeto Thread que se esta ejecutando\n * Thread.currentThread()\n\n<page_number>47</page_number>\n\n---\n\n\n## Page 48\n\n# Confinamiento dentro de hilos\n\n```java\nclass ServiceUsingThreadWithOutputStream {\n public void service() throws IOException {\n OutputStream output = new FileOutputStream(\"...\");\n Runnable r = new Runnable() {\n public void run() {\n try { doService(); } catch (IOException e) { }\n }\n };\n new ThreadWithOutputStream(r, output).start();\n }\n void doService() throws IOException {\n ThreadWithOutputStream.current().getOutput().write(0);\n }\n}\n```\n\n<img>Blue V icon</img> <img>Green checkmark circle</img>\n\n---\n\n```java\nclass ThreadWithOutputStream extends Thread {\n private OutputStream output;\n ThreadWithOutputStream(Runnable r, OutputStream s) {\n super(r);\n output = s;\n }\n static ThreadWithOutputStream current() throws ClassCastException {\n return (ThreadWithOutputStream) (currentThread());\n }\n static OutputStream getOutput() { return current().output; }\n static void setOutput(OutputStream s) { current().output = s; }\n}\n```\n\n<img>Red arrow labeled 2.a pointing to class definition</img>\n<img>Red arrow labeled 2.b pointing to method definitions</img>\n\n---\n\n\n## Page 49\n\n# Confinamiento dentro de hilos\n## java.lang.ThreadLocal\n\n* Permite que los datos específicos del hilo sean accesibles desde cualquier código de manera concurrentemente apropiada\n * Mantiene una tabla que asocia los datos específicos a instancias del Thread.ThreadLocal\n * Proporciona los métodos set y get para tener acceso a los datos que posee el Thread actual\n* Es una alternativa que elimina la dependencia de extensión sobre la clase Thread\n* Aplicaciones de ThreadLocal\n * Es una extensión del patrón de diseño Singleton\n * Crear una instancia de recurso por hilo accedida globalmente\n * Mantener información del contexto de seguridad\n * java.security.AccessControlContext\n * Problemas de seguimiento de variables globales estáticas\n\n<page_number>49</page_number>\n\n---\n\n\n## Page 50\n\n# Confinamiento dentro de hilos\n\n## java.lang.ThreadLocal\n\n```java\nclass ServiceUsingThreadLocal {\n static ThreadLocal output = new ThreadLocal();\n public void service() {\n try {\n final OutputStream s = new FileOutputStream(\"...\");\n Runnable r = new Runnable() {\n public void run() {\n output.set(s);\n try { doService(); } catch (IOException e) {}\n finally {\n try { s.close(); } catch (IOException ignore) {}\n }\n }\n };\n new Thread(r).start();\n } catch (IOException e) {}\n }\n void doService() throws IOException {\n ((OutputStream)(output.get())).write(0);\n // ...\n }\n}\n```\n\n<img>Blue V-shaped logo</img> <img>Green circle with white checkmark</img>\n\n<page_number>50</page_number>\n\n---\n\n\n## Page 51\n\n# Confinamiento de objetos\n\n* Cuando no se puede restringir el acceso a un **objeto anfitrión** dentro de un método o de un hilo\n * Se debe utilizar **bloqueo dinámico**\n * Restringir todos los accesos internos a ese **objeto**\n * Elimina la necesidad de bloqueos adicionales\n * El control de la exclusión para el **objeto anfitrión** se propaga automáticamente a todas sus partes internas\n * Asegurar la sincronización en todos los puntos de entrada del **objeto anfitrión.**\n * Objetos completamente sincronizados\n\n<page_number>51</page_number>\n\n---\n\n\n## Page 52\n\n# Confinamiento de objetos\n\n* El objeto anfitrión posee partes internas y es responsable de:\n * Construir nuevas instancias de cada objeto parte asignando referencia a campos privados\n * Nunca debe perder las referencias de los objetos parte\n * Debe tener sus métodos sincronizados\n * En la variante más conservadora, contención fija, el objeto anfitrión nunca reasigna los campos de referencia que apuntan a objetos parte internos\n\n\ngraph TD\n cliente --> anfitrión\n cliente --> anfitrión\n anfitrión --> subparte\n anfitrión --> parte1\n anfitrión --> parte2\n anfitrión -- \"cerrojo\" --> subparte\n\n\n<page_number>52</page_number>\n\n---\n\n\n## Page 53\n\n# Confinamiento de objetos\n## Adaptadores\n\n* Intención en contexto concurrente\n * Conectar objetos base no sincronizados dentro de objetos **anfitriones completamente sincronizado**\n * El anfitrión/adaptador proporciona el punto de entrada seguro\n* Aplicación\n * Dada una clase base no protegida, se puede definir una clase **adaptador sincronizada** con un campo, llamado **delegado**, que contiene una referencia al objeto base, el cuál envía peticiones\n * El acceso al delegado debe ser exclusivo\n * No es estrictamente necesario que sea final\n\n```mermaid\nclassDiagram\n class Base {\n +operacion()\n }\n class AdaptadorSincronizado {\n <>+operacion()\n }\n synchronized void operacion(){\n delegado.operacion()\n }\n AdaptadorSincronizado --> Base : delegado\n```\n<page_number>53</page_number>\n\n---\n\n\n## Page 54\n\n# Confinamiento de objetos\n## Adaptadores\n\n* Contexto de uso\n\n```java\nclass PuntoSimple {\n public double x;\n public double y;\n}\n\nclass PuntoSincronizado {\n\n protected final PuntoSimple delegado = new PuntoSimple();\n\n public synchronized double getX() {\n return delegado.x;\n }\n\n public synchronized double getY() {\n return delegado.y;\n }\n\n public synchronized void setX(double v) {\n delegado.x = v;\n }\n\n public synchronized void setY(double v) {\n delegado.y = v;\n }\n}\n```\n\n<img>Blue V logo</img> <img>Green circle with white checkmark</img>\n<page_number>54</page_number>\n\n---\n\n\n## Page 55\n\n# Confinamiento de objetos\n## Adaptadores\n\n* **Usos conocidos**\n * A excepción de la clase `java.util.Vector` y `java.util.HashTable` las clases básicas de la colección (`java.util.ArrayList`) no son sincronizadas\n * Las clases adaptadoras anónimas sincronizadas se construyen por medios de clases básicas\n Collection lista = Collections.synchronizedList(new ArrayList());\n * API `java.util.Collections`\n * Utiliza un wrapper (PD Decorador) para obtener una colección completamente sincronizada\n * Añade muchos métodos de envoltura del tipo\n public static Collection synchronizedCollection(Collection c)\n * Devuelve una colección sincronizada (segura en contextos de hilos) a partir de la colección especificada. Con el fin de garantizar el acceso secuencial\n\n<page_number>55</page_number>\n\n---\n\n\n## Page 56\n\n# Confinamiento de objetos\n## Creación de subclases\n\n* Alternativa a la delegación\n * Cuando se tiene la intención de que las instancias de una clase se confinen dentro de otras no hay razón para sincronizar sus métodos\n* Cuando se confinan unas y otras no, lo más seguro es sincronizar sus métodos\n\n```mermaid\nclassDiagram\n class Base {\n +operacion()\n }\n class ClaseSincronizado {\n <>+operacion()\n }\n Base <|-- ClaseSincronizado\n```\n<page_number>56</page_number>\n\n---\n\n\n## Page 57\n\n# Confinamiento de grupos\n\n* Para los grupos de objetos accesibles a través de múltiples hilos se puede asegurar para todos ellos que solamente uno de ellos pueda tener acceso a la vez a un **objeto recurso** determinado\n* Se asegura que el **recurso** sólo es poseído por un objeto\n* Se necesitan **protocolos** para mantener la propiedad de exclusividad sobre el recurso\n* Los **recurso** exclusivos son análogos a **objetos físicos**\n * Si se posee un recurso se puede hacer algo que no podría hacerse de otra manera\n * Si se posee, entonces ninguno otro lo tiene\n * Si se da a algún otro, entonces ya no se posee\n * Si se destruye nadie lo poseerá jamás\n\n<page_number>57</page_number>\n\n---\n\n\n## Page 58\n\n# Confinamiento de grupos\n\n* Otros nombres conocidos de recurso\n * Testigos = objetos lineales = capacidades = recursos\n* Problema\n * Los protocolos de transferencia del recurso son sencillos\n * Adquirir recurso, dar recurso, intercambiar recurso...\n * Los campos que mantienen referencias a objetos no actúan como referencias físicas\n * x.r = y.s no provoca que el Propietario y que contiene s pierda la posesión después de que se complete la sentencia de asignación\n * Análogo a problemas de la vida real derechos de propiedad intelectual\n\n<page_number>58</page_number>\n\n---\n\n\n## Page 59\n\n# Confinamiento de grupos\n## Protocolo\n\n* Los protocolos se pueden encapsular en los métodos realizando las distintas operaciones para distintos objetos Recursos **r** y **s**, y los objetos Propietarios **x** e **y** que pueden almacenarlos en un campo **ref**\n * Se muestran los cerrojos con bloques synchronized\n* Adquirir el Propietario **x** se aproapia inicialmente de **r**. Generalmente es el resultado de construir o inicializar **r** de la siguiente forma\n * `synchronized (this){ref = r}`\n* Olvidar el Propietario **x** hace que el uso de **r** no sea poseído por ningún propietario. Esto lo consigue el propietario actual realizando\n * `synchronized (this){ref = null}`\n\n<page_number>59</page_number>\n\n---\n\n\n## Page 60\n\n# Confinamiento de grupos\n## Protocolo\n\n* **Dar (set)** el Propietario y envía un mensaje al Propietario x que contiene un referencia al Recurso r como argumento, después de que y deje de tener posesión de r y se le ceda a x\n\n```java\nclass PropietarioX {\n Recurso ref;\n\n void set(Recurso r) {\n synchronized (this) {\n ref = r;\n }\n }\n}\n```\n<img>Blue V icon</img> <img>Green checkmark circle</img>\n\n```java\nclass PropietarioY {\n Recurso ref;\n\n void unaAccion(PropietarioX x) {\n Recurso r;\n synchronized (this) {\n r = ref;\n ref = null;\n }\n x.set(r);\n }\n}\n```\n<img>Blue V icon</img> <img>Green checkmark circle</img>\n<page_number>60</page_number>\n\n---\n\n\n## Page 61\n\n# Confinamiento de grupos\n## Protocolo\n\n* Coger (get) el Propietario y solicita el Recurso r al Propietario x que envía r como valor de retorno abandonando la posesión\n\n```java\nclass PropietarioX {\n Recurso ref;\n Recurso get() {\n synchronized (this) {\n Recurso r = ref;\n ref = null;\n return r;\n }\n }\n}\n```\n\n```java\nclass PropietarioY {\n Recurso ref;\n void otraAccion(PropietarioX x) {\n // ...\n Recurso r = x.get();\n synchronized (this) {\n ref = r;\n }\n }\n}\n```\n\n<page_number>61</page_number>\n\n---\n\n\n## Page 62\n\n# Confinamiento de grupos\n## Protocolo\n\n* **Intercambiar** el Propietario **y** cambia su Recurso **s** por el Recurso **r** al Propietario **x**. Esta operación se puede usar para coger un recurso por medio de `s=intercambiar(null)`, o para cederlo por medio de `intercambiar(r)`, ignorando el resultado\n\n```java\nclass PropietarioX {\n Recurso ref;\n Recurso intercambiar(Recurso s){\n synchronized (this) {\n Recurso r = ref;\n ref = s;\n return r;\n }\n }\n}\n```\n\n```java\nclass PropietarioY {\n Recurso ref;\n void otraAccionMas(PropietarioX x){\n // ...\n synchronized (this) {\n ref = x.intercambiar(ref);\n }\n }\n}\n```\n\nEjemplo de uso de protocolos\nUn objeto OutputStream confinado en el anfitrión que debe ser utilizado ocasionalmente por otros clientes <page_number>62</page_number>\n\n---\n\n\n## Page 63\n\n# Bibliografía\n\n* **Libros y manuales**\n * Doug Lea. Programación concurrente en Java: Principios y patrones de diseño. 2ª ed. PEARSON EDUCACION, 2000. Tema 2.\n http://gee.cs.oswego.edu/dl/cpj/.\n * Oracle. «Lesson: Concurrency (The Java™ Tutorials > Essential Classes)». Accedido marzo 4, 2014.\n http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html\n\n* **Enlaces de interés**\n * «Java Concurrent Animated | Free Home & Education software downloads at SourceForge.net». Accedido marzo 4, 2014.\n http://sourceforge.net/projects/javaconcurrenta/.\n\n<page_number>63</page_number>", "metadata": {} } } }