java - Nested synchronized block -


let's imagine have next classes:

public class service {     public void transfermoney(account fromacct, account toacct, int amount) {       synchronized (fromacct) {         synchronized (toaccount) { // use here 1 synchronized block?             fromacct.credit(amount);             toaccount.debit(amount);         }       }     } }  class account {   private int amount = 0;    public void credit(int sum) {     amount = amount + sum;   }    public void debit(int sum) {     amount = amount - sum;   } } 

for example know change state of fromacct , toacct objects in transfermoney method. rewrite our method 1 synchronized block?

public class service {  private final object mux = new object();   public void transfermoney(account fromacct, account toacct, int amount) {       synchronized(mux) {         fromacct.credit(amount);         toacct.debit(amount);       }  } } 

unless have unusual , particular need can't understand, seems me goal should protect account balance being corrupted multiple threads attempting credit or debit account @ same time.

the way this:

public class service {     public void transfermoney(account fromacct, account toacct, int amount) {         fromacct.credit(amount);         toaccount.debit(amount);     } }  class account {     private final object syncobject = new object();     private int amount = 0;      public void credit(int sum) {         synchronized(syncobject) {             amount = amount + sum;         }     }      public void debit(int sum) {         synchronized(syncobject) {             amount = amount - sum;         }     } } 

if goal during money transfer ensure both credit , debit actions occur 1 transaction, or atomically, using synchronizing not right approach. in synchronized block, if exception occur, lose guarantee both actions occur atomically.

implementing transactions complex topic, why use databases us.

edit: op asked: difference between example (one synchronized block mux) , yours synchronized in account class?

that's fair question. there few differences. main difference that, ironically, example over-synchronizes. in other words, though using single synchronized block, performance going worse, potentially.

consider following example: have 4 different bank accounts: let's name them a, b, c, d. , have 2 money transfers initiated @ exact same time:

  1. money transfer account account b.
  2. money transfer account c account d.

i think agree because 2 money transfers occurring on separate accounts, there should no harm (no risk of corruption) in executing both money transfers @ same time, right?

yet, example, money transfers can execute 1 after another. mine, both money transfers occur simultaneously, yet safely well. block if both money transfers attempt "touch" same accounts.

now imagine if use code process hundreds, thousands or more concurrent money transfers. there no doubt example perform lot better yours, while still retaining thread safety, , protecting correctness of account's balance.

in effect, version of code conceptually behaves lot more original 2-synchronized block code. except following improvements:

  • fixes potential deadlock scenario.
  • intent clearer.
  • provides better encapsulation. (meaning if other code outside transfermoney method try debit or credit amounts, still retain thread safety, while not. know said not case, version, design absolutely guarantees it)

Comments

Popular posts from this blog

Magento/PHP - Get phones on all members in a customer group -

php - .htaccess mod_rewrite for dynamic url which has domain names -

Website Login Issue developed in magento -