Java Tutorials - Herong's Tutorial Examples - Version 7.03, by Dr. Herong Yang
BankingThread.java - Synchronization Sample Program
This section provides a tutorial example on how to solve the banking synchronization issue with Java synchronized methods.
Now, let's write a Java program to see how the synchronization technique can solve the bank problem. Two classes are designed to simulate a bank system:
BankingThread class:
/* BankingThread.java - Copyright (c) 2014, HerongYang.com, All Rights Reserved. */ import java.util.*; public class BankingThread extends Thread { private long[] t_balance; // acount balance private long t_count; // number of transactions done so far public BankingThread(ThreadGroup g, String n) { super(g,n); t_count = 0; int m = BankingMain.accountCount(); t_balance = new long[m]; for (int i=0; i<m; i++) t_balance[i] = 0; } public long transactionCount() { return t_count; } public long getBalance(int i) { return t_balance[i]; } public void run() { while (!isInterrupted()) { t_count++; Random r = BankingMain.getRandom(); long t_step = BankingMain.getStep(); int m = BankingMain.accountCount(); int n = r.nextInt(m); // account number int t = 2*r.nextInt(2)-1; // type of transaction long a = (long) t*r.nextInt(10000); // amount of transaction if (t_step==1) if (BankingMain.doTransaction1(n,a)) t_balance[n] += a; if (t_step==2) if (BankingMain.doTransaction2(n,a)) t_balance[n] += a; if (t_step==3) if (BankingMain.doTransaction3(n,a)) t_balance[n] += a; if (t_step==4) if (BankingMain.doTransaction4(n,a)) t_balance[n] += a; try { sleep(10); // wait for the next customer } catch (InterruptedException e) { break; } } } }
BankingMain class:
/* BankingMain.java - Copyright (c) 2014, HerongYang.com, All Rights Reserved. */ import java.util.*; public class BankingMain { public static final int a_maxi = 10; // number of accounts public static long[] balance = new long[a_maxi]; public static Random r_number; private static final int t_maxi = 5; // number of threads private static BankingThread[] t_list = new BankingThread[t_maxi]; private static long t_step; private static Object o_lock; private static Object[] a_lock = new Object[a_maxi]; public static void main(String[] a) { o_lock = new Object(); for (int i=0; i<a_maxi; i++) a_lock[i] = new Object(); t_step = 1; // using doTransaction1(); System.out.println("No synchronization:"); testATM(); printResult(); t_step = 2; // using doTransaction2(); System.out.println("Synchronized method:"); testATM(); printResult(); t_step = 3; // using doTransaction3(); System.out.println("Synchronized statements:"); testATM(); printResult(); t_step = 4; // using doTransaction4(); System.out.println("Synchronized statements per account:"); testATM(); printResult(); } private static void testATM() { for (int i=0; i<a_maxi; i++) balance[i] = 0; r_number = new Random(); ThreadGroup g = new ThreadGroup("ATM"); for (int i=0; i<t_maxi; i++) { BankingThread t = new BankingThread(g,String.valueOf(i)); t.start(); t_list[i] = t; } try { Thread.sleep(5*1000); // working period } catch (InterruptedException e) { System.out.println("Interrupted in the mainthread."); } g.interrupt(); while (g.activeCount()>0); // wait for all threads to end } private static void printResult() { System.out.print("Account"); for (int i=0; i<t_maxi; i++) System.out.print(", ATM "+i); System.out.print(", Transaction Sum, Balance"); for (int j=0; j<a_maxi; j++) { System.out.print("\n"+j); long sum = 0; for (int i=0; i<t_maxi; i++) { sum += t_list[i].getBalance(j); System.out.print(", " +getCurrency(t_list[i].getBalance(j))); } System.out.print(", "+getCurrency(sum)+ ", "+getCurrency(balance[j])); } System.out.print("\n# of Transactions"); for (int i=0; i<t_maxi; i++) System.out.print(", "+t_list[i].transactionCount()); System.out.print("\n"); } private static String getCurrency(long d) { long i = d/100; long f = Math.abs(d)%100; String fs = String.valueOf(f); if (f<10) fs = "0"+fs; return String.valueOf(i)+"."+fs; } public static long getStep() { return t_step; } public static int accountCount() { return a_maxi; } public static Random getRandom() { return r_number; } public static long getBalance(int i) { return balance[i]; } public static boolean doTransaction1(int i, long a) { boolean ok = false; long c = balance[i]; // get current balance ok = c+a>0; if (ok) { // stop accout balance going negative try { Thread.sleep(1); // slow down the process } catch (InterruptedException e) { Thread.currentThread().interrupt(); // re-set the flag } balance[i] = c+a; // set current balance } return ok; } public synchronized static boolean doTransaction2(int i, long a) { boolean ok = false; long c = balance[i]; // get current balance ok = c+a>0; if (ok) { // stop accout balance going negative try { Thread.sleep(1); // slow down the process } catch (InterruptedException e) { Thread.currentThread().interrupt(); // re-set the flag } balance[i] = c+a; // set current balance } return ok; } public static boolean doTransaction3(int i, long a) { boolean ok = false; synchronized (o_lock) { long c = balance[i]; // get current balance ok = c+a>0; if (ok) { // stop accout balance going negative try { Thread.sleep(1); // slow down the process } catch (InterruptedException e) { Thread.currentThread().interrupt(); // re-set the flag } balance[i] = c+a; // set current balance } } return ok; } public static boolean doTransaction4(int i, long a) { boolean ok = false; synchronized (a_lock[i]) { long c = balance[i]; // get current balance ok = c+a>0; if (ok) { // stop accout balance going negative try { Thread.sleep(1); // slow down the process } catch (InterruptedException e) { Thread.currentThread().interrupt(); // re-set the flag } balance[i] = c+a; // set current balance } } return ok; } }
Couple of notes about this program:
See the next section for the execution output.
Last update: 2014.
Table of Contents
Execution Process, Entry Point, Input and Output
Primitive Data Types and Literals
Bits, Bytes, Bitwise and Shift Operations
Managing Bit Strings in Byte Arrays
Reference Data Types and Variables
StringBuffer - The String Buffer Class
System Properties and Runtime Object Methods
Generic Classes and Parameterized Types
Generic Methods and Type Inference
Lambda Expressions and Method References
Execution Threads and Multi-Threading Java Programs
ThreadGroup Class and "system" ThreadGroup Tree
►Synchronization Technique and Synchronized Code Blocks
Why Synchronization Is Needed in Multi-Threading Applications?
Synchronization Technique - Lock and Synchronized Code
"synchronized" - How Java Supports Synchronization
►BankingThread.java - Synchronization Sample Program
BankingThread.java - Synchronization Sample Program Output
Deadlock Condition Example Programs