SberTech ♥ Open Source, concurrencia y operaciones bancarias confiables: análisis de soluciones a problemas con Joker 2018

Este fin de semana fue Joker 2018 , ¡fue interesante! Pero la conferencia fue rica no solo en discursos. Todas las empresas patrocinadoras intentaron destacarse en el contexto de los "competidores" y no somos una excepción.

Hubo muchas cosas interesantes en el stand de Sberbank Technologies, pero quiero hablar sobre lo que destacamos. Nuestro equipo de desarrollo Apache Ignite en SberTech preparó las tareas y realizó un sorteo entre quienes se atrevieron a resolverlas.

Debajo del corte, encontrará tareas, análisis de soluciones y la capacidad de justificar su propia versión de la solución en los comentarios.



¡Ay, comensales!


Petya y Kolya comprometen una función por día en Apache Ignite .

Masha prueba rápidamente cada función y revierte las confirmaciones que contienen errores.
Cada tercera confirmación inicial de Petit y la quinta de Kolya contienen un error.
Petya pasa 2 días adicionales para corregir el error, Kolya 3, y nuevamente lo hacen
comprometerse

¿Cuántas funciones se comunicarán en 86 días hábiles si a Masha le gusta Petya,
y ella se da cuenta de su error solo en ese día cuando solo él está equivocado?

Solución
A partir del día 13, se forma un ciclo que le permite a Petya corregir solo cada segundo error.

La respuesta
64 + 54 = 118;

Villaribo y Villabaggio


Procesar un banco no confiable durante las operaciones en un grupo de cuentas bloquea claves
cuentas en el orden de su declaración en la operación, es decir de izquierda a derecha
Cada punto muerto se resuelve manualmente por los especialistas del banco y requiere 10 veces más.
tiempo de funcionamiento normal.
Procesar un banco confiable siempre bloquea las teclas ascendentes, pero gasta 2
veces más que una transacción normal en un banco poco confiable.
Ambos bancos tienen 10 cuentas, las claves de las cuentas son números del 1 al 10.
El procesamiento de cada banco requiere 12 operaciones.
Las operaciones se realizan en paralelo, de dos en dos. Cada operación afecta hasta 3
cuentas:
- operación n. ° 1 (cuentas: A, B, C), donde A = i, B = A + 1, C = (A + B)% 10,
- operación n. ° 2 (cuentas: D, E, F), donde D = 11-i, E = D-1, F = (D + E)% 10,
i varía de 1 a 6.
La ejecución del siguiente par de operaciones comienza solo después de completarse
El anterior.
Las claves se bloquean de acuerdo con la política del banco, una en cada una de las operaciones, comenzando
de la operación número 1.
Si la clave ya está bloqueada en una de las operaciones, pero se requiere para realizar otra,
entonces primero se completa la primera operación, luego continúa la segunda.
Se espera que la ejecución forzada de un par de operaciones en modo secuencial ocurra 2 veces más lento que en paralelo.
¿Qué banco y cuántas veces más rápido completarán las operaciones?

Pista
Total:
- 6 iteraciones,
- 12 operaciones
- en todas las operaciones excepto una, 3 teclas cada una.

Solución
Si todas las claves son diferentes, es posible la ejecución paralela.
Si no, entonces no, y el punto muerto es posible.

Cálculos
Un banco poco confiable gasta en una transacción 1 "tacto", 2 en el caso de "dificultades" y hasta 10 en el caso de un punto muerto.
Un banco confiable gasta en la transacción 2 "medidas" y 4 en caso de "dificultades". No hay puntos muertos confiables.

La respuesta
Completo al mismo tiempo.

Riesgos del repositorio público


Serezha es una programadora muy experimentada, extremadamente apostadora e infinitamente codiciosa.
Una vez que encontró el código fuente de su bolsa favorita en un github.
¿Cuál es la apuesta mínima que Seryozha puede ganar?

Se adjunta una lista de bolsas simplificada:

class Bid { //  int amount; boolean checked; boolean restricted; Bid(int amount) {this.amount = amount;} } ~~~ AtomicReference<Bid> ref = new AtomicReference<>(); volatile boolean winner = false; ~~~ Thread validator = new Thread(() -> { //  ! while (true) { Bid bid = ref.get(); if (bid == null) continue; if ((((bid.amount << 5) ^ 1_000_000) >>> 6) < (2 << 15)) bid.restricted = true; bid.checked = true; } }); Thread payer = new Thread(() -> { //  ! while (true) { Bid bid = ref.get(); if (bid == null) continue; if (bid.checked) { if (!bid.restricted) winner = true; // ! ref.set(null); } } }); ~~~ synchronized boolean makeMeRich(int amount){ //    ? if (winner) return false; //    -    ref.set(new Bid(amount)); while(ref.get() != null) sleep(1); return winner; //   "true" -     } 

Consejo # 1
- 131072?
- No, sal de la trampa :)
Consejo # 2
¿Cuál es la apuesta mínima que Seryozha puede ganar?
Consejo # 3
 th1{ bid.restricted = true; bid.checked = true; } ... th2{ while (!bid.checked) { sleep(1); } assert bid.restricted; // 99.999% } 

No hay garantías de visibilidad intuitivamente esperadas.

Puede agregarlos de la siguiente manera:

 volatile boolean checked; 

Consejo # 4
¿Cuál es la apuesta mínima que Seryozha puede ganar?
Solución

La respuesta
 java.lang.Integer#MIN_VALUE 

Sin embargo, "0" e incluso "1" se consideraron como la decisión correcta.

Ganadores


Lo mejor de todo resolvió el problema
- Evgeny Zubenko
- Alexander Novikov
- Andrey Golikov

Los muchachos obtuvieron mochilas de marca, camisetas y, por supuesto, libros.

Source: https://habr.com/ru/post/es426639/


All Articles