Quiero hacer un banco simple usando un hilo en Java. Pero no puedo hacer depósito(), retirar() para sincronizar. No hay saldo sincronizado todo el tiempo. Escribo la palabra clave 'sincronizada' en el nombre del método, pero nunca funciona. Además, hago 'synchronizedList' en mi ArrayList (debería usar la lista de arreglos para hacer esto) pero nunca funciona. ¿Cómo puedo obtener un saldo adecuado? por favor, ayúdame.
import java.security.SecureRandom; public class Transaction implements Runnable { private static final SecureRandom generator = new SecureRandom(); private final int sleepTime; // random sleep time for thread private String transaction; private int amount; private static int balance; private Account account = new Account(); public Transaction (String transaction, int amount) { this.transaction = transaction; this.amount = amount; sleepTime = generator.nextInt(2000); } @Override public void run() { // TODO Auto-generated method stub try { if(transaction == "deposit") { balance = account.deposit(amount); } else if (transaction == "withdraw") { balance = account.withdraw(amount); } System.out.println("[" + transaction + "] amount : " + amount +" balance : " + balance); Thread.sleep(sleepTime); }catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); // re-interrupt the thread } } } import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class AccountTest { public static void main(String[] args) { // TODO Auto-generated method stub // create ArrayList List<Transaction> john = Collections.synchronizedList(new ArrayList<>()); // add Transaction objects john.add(new Transaction("deposit", 1000)); john.add(new Transaction("withdraw", 500)); john.add(new Transaction("withdraw", 200)); john.add(new Transaction("deposit", 3000)); // execute Thread Pool ExecutorService executorService = Executors.newCachedThreadPool(); // start transactions for(int i=0; i<john.size(); i++) { executorService.execute(john.get(i)); } // shut down Thread Pool } } public class Account { // deposit withdraw private static int balance; public synchronized int deposit(int amount) { balance += amount; return balance; } public synchronized int withdraw(int amount) { balance -= amount; return balance; } }El error central aquí es que cada Transacción tiene su propia Cuenta. Cada subproceso adquiere el bloqueo en su propia instancia de Cuenta, con el resultado de que no se está produciendo un bloqueo real.
Necesita un bloqueo que se comparte entre los subprocesos, deben intentar modificar el mismo objeto Cuenta. Los métodos de instancia marcados con synchronized adquieren un bloqueo integrado en la instancia del objeto.
Hacer que el saldo de la cuenta sea estático es un truco sucio que hace que todos los datos del saldo terminen en el mismo lugar (lo que funciona solo si tiene una sola cuenta) pero no soluciona el problema de sincronización.
(También podría cambiar los métodos de la cuenta para que sean estáticos, y eso solucionaría el problema de sincronización, ya que todos los subprocesos adquirirían el bloqueo en la clase, y solo hay una clase. Pero, por supuesto, deja de funcionar una vez que necesita una segunda cuenta por lo que no es una gran solución.)
Reutilice esto para que, en lugar de que cada Transacción cree su propia cuenta, comparta el mismo objeto Cuenta en todas las Transacciones. Puede pasar la Cuenta a la Transacción como un argumento constructor.