Once, multithreading java base de la profundidad de la cerradura

Un bloqueo de reentrada

1. bloqueo como un compartir datos concurrentes para garantizar la coherencia de las herramientas, la plataforma JAVA en múltiples implementaciones (como sincronizado (peso pesado) y ReentrantLock (peso ligero), y así sucesivamente). Estas cerraduras han sido oferta para proporcionar comodidad para nuestro desarrollo por escrito. cerradura reentrante, también conocido como cerraduras recursivas, refiriéndose al mismo hilo después de la función externa para obtener un bloqueo, las funciones recursivas interiores todavía tiene que adquirir el código de bloqueo, pero no se ve afectada.
2. Entorno En ReentrantLock JAVA y están sincronizados de bloqueo de reentrada.

3. Código

//重入锁  轻量级(Lock)与重量级锁(synchronized)---可重入性(递归锁)
public class Test001 implements Runnable {
    @Override
    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        set();
    }
    //synchronized代码块执行完毕的时候释放锁
    private synchronized void set() {
        System.out.println("set方法");
        get();
    }
    private synchronized void get() {
        System.out.println("synchronized  可具备可重入性-get方法");
    }
    public static void main(String[] args) {
        Test001 test001 = new Test001();
        Thread thread = new Thread(test001);
        thread.start();
        System.out.println(Thread.currentThread().getName()+"主线程结束");
    }
}

4. resultados

main主线程结束
set方法
synchronized  可具备可重入性-get方法

5. Código

//演示lock锁是否具备  可重入性(特征:锁可以传递(方法递归传递)),下面的方法为啥会调两次,因为最后一次调用他已经知道第一次已经上锁了(不会在重新获取锁)
public class Test002 implements Runnable {
    Lock lock = new ReentrantLock();

    @Override
    public void run() {
        set();
    }

    private void set() {
        try {
            //上锁
            lock.lock();
            System.out.println("set方法");
            get();
        } catch (Exception e) {
            //重入锁的目的就是避免死锁
        } finally {
            lock.unlock();//释放锁
        }
    }

    private void get() {
        try {
            lock.lock();
            System.out.println("lock  可具备可重入性-get方法");
        } catch (Exception e) {

        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        Test002 test002 = new Test002();
        Thread thread = new Thread(test002);
        thread.start();
    }
}

6. resultados

set方法
lock  可具备可重入性-get方法

En segundo lugar, bloqueos de escritura-lectura

1. En comparación Java en la cerradura (cerraduras en Java) cerraduras en aplicación de bloqueo, de lectura y escritura más complicado. Suponga que su programa consiste en una serie de operaciones de lectura y escritura a los recursos compartidos, leer y operaciones de escritura no son tan frecuentes. En ausencia de una operación de escritura , dos hilos para leer un recurso sin ningún problema, se debe permitir que múltiples hilos pueden leer el recurso compartido al mismo tiempo. Pero si hay una falta de hilo para escribir estos recursos compartidos, ya no debemos tener los recursos para otros hilos para leer o escribir (Nota del traductor: En otras palabras: Leer - pueden coexistir, lectura - escritura no puede coexistir, escritura - escritura no podemos coexistir). Esto requiere un bloqueo de lectura / escritura para resolver este problema. En Java5 paquete java.util.concurrent ya contiene un bloqueo de lectura-escritura. Sin embargo, debemos entender los principios detrás de su implementación.

2. Código

//读写锁  jvm内置缓存
public class Test003 {
    private volatile Map<String,String> caChe = new HashMap<>();
    //读写锁
    private ReentrantReadWriteLock  rw1 = new ReentrantReadWriteLock();
    //写入锁
    private WriteLock writeLock = rw1.writeLock();
    //读出锁
    private ReadLock readLock = rw1.readLock();
    //写入元素
    public void put(String key,String value){
        try {
            writeLock.lock();
            System.out.println("正在做写的操作,key:" + key + ",value:" + value + "开始.");
            Thread.sleep(100);
            caChe.put(key,value);
            System.out.println("正在做写的操作,key:" + key + ",value:" + value + "结束.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
    }
    //读取元素
    public String get(String key){
        try {
            readLock.lock();
            System.out.println("正在做读的操作,key:" + key + ",开始.");
            Thread.sleep(100);
            String value = caChe.get(key);
            System.out.println("正在做读的操作,key:" + key + ",结束.");
            return value;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        }finally {
            readLock.unlock();
        }
    }

    public static void main(String[] args) {
        Test003 test003 = new Test003();
        //写线程
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0;i<10;i++){
                    test003.put("i",i+"");
                }
            }
        });
        //读线程
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0;i<10;i++){
                    test003.get(i+"");
                }
            }
        });
        t1.start();
        t2.start();
    }
}

3. resultados

正在做写的操作,key:i,value:0开始.
正在做写的操作,key:i,value:0结束.
正在做写的操作,key:i,value:1开始.
正在做写的操作,key:i,value:1结束.
正在做读的操作,key:0,开始.
正在做读的操作,key:0,结束.
正在做写的操作,key:i,value:2开始.
正在做写的操作,key:i,value:2结束.
正在做写的操作,key:i,value:3开始.
正在做写的操作,key:i,value:3结束.
正在做写的操作,key:i,value:4开始.
正在做写的操作,key:i,value:4结束.
正在做读的操作,key:1,开始.
正在做读的操作,key:1,结束.
正在做写的操作,key:i,value:5开始.
正在做写的操作,key:i,value:5结束.
正在做写的操作,key:i,value:6开始.
正在做写的操作,key:i,value:6结束.
正在做写的操作,key:i,value:7开始.
正在做写的操作,key:i,value:7结束.
正在做读的操作,key:2,开始.
正在做读的操作,key:2,结束.
正在做写的操作,key:i,value:8开始.
正在做写的操作,key:i,value:8结束.
正在做写的操作,key:i,value:9开始.
正在做写的操作,key:i,value:9结束.
正在做读的操作,key:3,开始.
正在做读的操作,key:3,结束.
正在做读的操作,key:4,开始.
正在做读的操作,key:4,结束.
正在做读的操作,key:5,开始.
正在做读的操作,key:5,结束.
正在做读的操作,key:6,开始.
正在做读的操作,key:6,结束.
正在做读的操作,key:7,开始.
正在做读的操作,key:7,结束.
正在做读的操作,key:8,开始.
正在做读的操作,key:8,结束.
正在做读的操作,key:9,开始.
正在做读的操作,key:9,结束.

En tercer lugar, el bloqueo pesimista y optimista de bloqueo

1. bloqueo pesimista

Siempre asuma el peor de los casos, todos los otros piensan modifica hilo al obtener los datos, se bloqueará (bloqueo de lectura, bloqueo de escritura, bloqueo de línea, etc.), cuando otros hilos que quieran acceder a los datos, hay que aferrarse bloqueado . Puede contar con la aplicación de base de datos, tales como bloqueos de registro, leer y bloqueos de escritura, están bloqueados antes de la operación, en Java, el pensamiento es sincronizado bloqueo pesimista.

2. El bloqueo optimista

2.1. Siempre piensa no hay problemas de concurrencia, cada vez para obtener los datos y creen que no habrá otros hilos para modificar los datos, no será cerrada, pero cuando la actualización determinará otro hilo antes de que no está modificar los datos, por lo general un número de versión o mecanismo de funcionamiento CAS de lograr.

 versión: Largo además de un número de versión de datos es el campo de versión en la tabla de datos representa el número de datos es modificado, y cuando se modifican los datos, además de un valor de versión. Cuando un hilo de A a actualizar los valores de los datos será leído valor de versión durante la lectura de los datos, al presentar la actualización, si es sólo para leer la versión cuando la actualización es la versión igual valor en la base de datos actual, o reintento actualización hasta que la actualización se realiza correctamente.

declaraciones núcleo SQL

actualización del conjunto de mesa x = x + 1, version = Versión + 1 donde id = # {id} y la versión # = {version};    

operación CAS: es decir, comparar y de intercambio, o comparar y set, que implica tres operandos, donde el valor de la memoria de datos, valor esperado, el nuevo valor. Cuando es necesario actualizar, se determina a tomar un valor antes de que el valor actual de la memoria son iguales, si es igual, actualizada con el nuevo valor, si el intento falla, una operación general de giro, es decir, de forma continua reintentos.

2.2. Ejemplos

Para poner un ejemplo sencillo: supongamos que la información de la cuenta en la tabla de base de datos tiene un campo de versión, un valor actual de 1; campo y el saldo de la cuenta corriente (Balance) es de $ 100.

  1. En este momento, el operador de la A a la lectura a (version = 1), y deduciendo los $ 50 ($ 100- $ 50) del saldo de la cuenta.
  2. Durante el funcionamiento del operador A, el operador B también lee la información de usuario (version = 1), y se deducirán del saldo de la cuenta es $ 20 ($ 100- $ 20).
  3. El operador de una revisión completa del número de versión de datos más uno (version = 2), junto con el saldo de la cuenta deducciones (equilibrio = $ 50), comprometida con la actualización de la base de datos, esta vez debido al presentar la versión de datos es mayor que la base de datos registra la versión actual de los datos es registro de base de datos actualizada se actualiza a la versión 2.
  4. El operador B para completar la operación, sino también el número de versión más uno (version = 2) intenta enviar datos (equilibrio = $ 80) a la base de datos, pero esta vez que el descubrimiento de la versión de registro de base de datos, el número de versión de los datos del operador B, presentada el 2 de la base de datos también registra la actual versión 2, no cumple con la "submit versión debe ser mayor que la versión actual del registro con el fin de realizar la actualización," la estrategia de bloqueo optimista, por lo tanto, se rechazó la presentación operador B.

Por lo tanto, para evitar que el operador B con la cubierta del resultado de la operación del operador A puede estar basada en la antigua versión = 1 modificados resultados de los datos.

En cuarto lugar, el fin de la

¡¡¡Siempre mantén la fe!!!

Publicados 122 artículos originales · ganado elogios 64 · Vistas a 50000 +

Supongo que te gusta

Origin blog.csdn.net/chenmingxu438521/article/details/103872814
Recomendado
Clasificación