Java Tutorials - Herong's Tutorial Notes
Dr. Herong Yang, Version 6.00

BankingThread.java - Synchronization Sample Program Output

This section provides a tutorial example on how to solve the banking synchronization issue with Java synchronized methods.

Here is the output of the sample program presented in the previous section:

No synchronization:
Account, ATM 0, ATM 1, ATM 2, ATM 3, ATM 4, Transaction Sum, Balance
0, 506.81, 227.06, 286.89, -885.14, 330.11, 465.73, 1051.87
1, 63.98, 27.74, 413.05, 276.93, -86.81, 694.89, 529.10
2, -303.05, -283.53, 385.71, 126.36, 136.16, 61.65, 188.65
3, -62.36, 491.84, 172.51, -548.71, 63.59, 116.87, 182.85
4, 553.12, 22.86, 1027.99, 52.98, -202.90, 1454.05, 1297.92
5, 276.85, 33.59, -371.78, -36.76, 363.60, 265.50, 343.82
6, 313.82, 300.44, 64.48, -321.91, 651.41, 1008.24, 1532.09
7, -516.72, -22.58, -139.76, -7.58, 352.92, -333.72, 264.26
8, 19.66, -506.82, 469.41, 437.11, -106.23, 313.13, 243.39
9, 225.69, -64.89, -301.68, -128.40, 103.83, -165.45, 173.74
# of Transactions, 444, 443, 443, 444, 443
Synchronized method:
Account, ATM 0, ATM 1, ATM 2, ATM 3, ATM 4, Transaction Sum, Balance
0, 109.68, 206.15, 482.22, 297.49, -59.65, 1035.89, 1035.89
1, -123.26, -229.60, 369.57, 187.18, -198.98, 4.91, 4.91
2, 326.85, 247.02, -124.56, 68.14, 437.90, 955.35, 955.35
3, -83.52, 154.05, 104.15, 313.32, -216.91, 271.09, 271.09
4, 274.77, 251.13, 153.58, 147.35, 17.41, 844.24, 844.24
5, 137.12, -196.64, -17.36, 243.93, 20.02, 187.07, 187.07
6, -53.76, -19.88, -251.28, 461.91, 117.58, 254.57, 254.57
7, 69.14, -3.91, -88.01, 173.90, -94.96, 56.16, 56.16
8, 390.75, -57.51, 270.10, 146.84, -1.44, 748.74, 748.74
9, -115.88, -264.73, 152.22, 241.86, 142.41, 155.88, 155.88
# of Transactions, 169, 166, 168, 166, 167
Synchronized statements:
Account, ATM 0, ATM 1, ATM 2, ATM 3, ATM 4, Transaction Sum, Balance
0, 157.37, 164.54, 247.90, -161.94, -75.02, 332.85, 332.85
1, -4.53, -48.39, 140.97, -31.71, 245.28, 301.62, 301.62
2, 313.45, 21.60, 235.10, 121.30, 260.76, 952.21, 952.21
3, -157.13, -75.60, 343.08, 288.97, 143.18, 542.50, 542.50
4, 29.81, 284.44, -81.49, -324.18, 160.94, 69.52, 69.52
5, 512.93, 303.73, 73.00, 72.01, 172.37, 1134.04, 1134.04
6, 312.77, 26.97, 29.00, -274.98, 6.03, 99.79, 99.79
7, -67.18, 28.11, 188.62, -104.12, 36.09, 81.52, 81.52
8, 31.48, 451.04, 174.24, 5.17, 287.17, 949.10, 949.10
9, -72.96, -58.93, -80.25, -35.12, 285.98, 38.72, 38.72
# of Transactions, 172, 170, 170, 170, 167
Synchronized statements per account:
Account, ATM 0, ATM 1, ATM 2, ATM 3, ATM 4, Transaction Sum, Balance
0, -356.88, 230.09, 121.05, 17.74, 139.69, 151.69, 151.69
1, 196.23, 160.88, 435.08, -321.64, -293.67, 176.88, 176.88
2, 42.31, -83.73, 220.07, 355.22, -255.00, 278.87, 278.87
3, -50.23, 794.38, -48.61, -266.61, 411.13, 840.06, 840.06
4, -149.40, -92.54, -11.21, 561.98, -47.66, 261.17, 261.17
5, -55.14, 230.12, 103.13, -107.65, 263.93, 434.39, 434.39
6, 442.87, 115.36, 55.61, -96.76, -142.20, 374.88, 374.88
7, -90.27, -17.98, 98.67, -19.88, 224.26, 194.80, 194.80
8, 86.30, 74.51, 148.25, 464.22, 290.62, 1063.90, 1063.90
9, 652.21, 5.67, -58.23, 69.86, 250.82, 920.33, 920.33
# of Transactions, 281, 287, 281, 282, 287

By looking at the output, we can see that:

  • Without any synchronization, doTransaction1(), we can see that every account was corrupted. For example, the balance of account number 0 was reported as 1051.87 by the BankingMain class, but it should be 465.73, which is the sum of balances from all the threads on account number 0.
  • With the synchronized method, doTransaction2(), the balances in the BankingMain class were maintained perfectly correct, but the performance of the threads were reduced dramatically. Without synchronization, BnakingThread was performing about 444 transactions in 5 seconds. But with the synchronized method, it was performing only about 169 transactions.
  • By moving the synchronization from the method level to statements level, doTransaction3(), the performance improved slightly, from 169 transactions to 172 transactions.
  • By replacing the central lock, o_lock, with individual locks per account, a_lock[i], the performance improved dramatically, from 172 transactions to 281 transactions. With the central lock, we were putting all other threads on hold while one thread was running the synchronized block. With the individual locks, we were putting only other threads on hold if they happened to work on the same account number as the thread who was running the synchronized block. The chance of this situation is only about 1 over the number of accounts. As the number of accounts increases, the BankingThread will perform better and better.

Exercise: Assuming the following class is used in a multiple-threaded program:

public class C {
   public static synchronized void m1() {
      statement block_1
   }
   public synchronized void m2() {
      statement block_2
   }
   public synchronized void m3() {
      statement block_3
   }
   public void m4() {
      synchronized (this) {
         statement block_4
      }
   }
}
  • Is it possible that block_1 in one thread could be on hold because of block_1 is running another thread?
  • Is it possible that block_1 in one thread could be on hold because of block_2 is running another thread?
  • Is it possible that block_2 in one thread could be on hold because of block_1 is running another thread?
  • Is it possible that block_2 in one thread could be on hold because of block_2 is running another thread?
  • Is it possible that block_2 in one thread could be on hold because of block_3 is running another thread?
  • Is it possible that block_2 in one thread could be on hold because of block_4 is running another thread?

Sections in This Chapter

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

Dr. Herong Yang, updated in 2008
BankingThread.java - Synchronization Sample Program Output