Javaのスレッド同期の3つの方法

13016 ワード

1つ目:同期コードブロック
同期コードブロックの核心は同期モニタを設定することであり、原則としてJavaでは任意のオブジェクトを同期モニタとして設定することができるが、通常は同時アクセス可能な共有リソースオブジェクトを同期モニタとして設定する.構文の形式は次のとおりです.
synchronized(obj) {
……
}
同じアカウントに対する複数のユーザーの引き出し操作をシミュレートするコードの例:
   1: //              ,         
   2:     public void run() {
   3:         synchronized(account) {
   4:             //             
   5:             if (account.getBalance() >= drawAmount) {
   6:                 //  
   7:                 System.out.println(getName() + "    ,    :" + drawAmount);
   8:                 
   9:                 //    
  10:                 account.setBalance(account.getBalance() - drawAmount);
  11:                 System.out.println("\t   :" + account.getBalance());
  12:             }
  13:             else {
  14:                 System.out.println("    ,    !");
  15:             }
  16:         }
  17:         
  18:     }

2つ目:同期方法
同期メソッドは、同期コードブロックの変形と見なすことができ、指定した同期モニタを表示する必要はありませんが、実際には自分のthisを同期モニタと見なすので、同期メソッドは操作するクラスの内部に定義されていることがわかります.サンプルコードは、お金を引き出す操作をシミュレートします.
   1: package org.frzh.thread;
   2:  
   3: public class Account2 {
   4:     private String accountNo;
   5:     private double balance;
   6:     
   7:     public Account2() {}
   8:     public Account2(String accountNo, double balance) {
   9:         this.accountNo = accountNo;
  10:         this.balance = balance;
  11:     }
  12:     
  13:     public double getBalance() {
  14:         return this.balance;
  15:     }
  16:     //      
  17:     public synchronized void draw(double drawAmount) {
  18:         //             
  19:         if (this.balance >= drawAmount) {
  20:             //  
  21:             System.out.println(Thread.currentThread().getName() + "    ,    :" + drawAmount);
  22:             
  23:             //    
  24:             this.balance -= drawAmount;
  25:             System.out.println("\t   :" + this.balance);
  26:         }
  27:         else {
  28:             System.out.println("    ,    !");
  29:         }
  30:     }
  31: }

同期方法と同期コードライブラリの比較では,同期方法はオブジェクト向けプログラミングの考え方に合致する.
3つ目:同期ロック(Lock)
同期ロックは、スレッドが共有リソースにアクセスするときにリソースをロックし、他のスレッドが共有リソースにアクセスすることは許可されず、操作が完了した後に同期ロックを解放します(呼び出しを表示する必要があります).同期コードブロックと同期方法を比較すると、同期ロックはより柔軟に見え、もちろん最も太くなりやすい.サンプルコード:
   1: package org.frzh.thread;
   2:  
   3: import java.util.concurrent.locks.ReentrantLock;
   4:  
   5: public class Account3 {
   6:     //     
   7:     private final ReentrantLock lock = new ReentrantLock();    //    
   8:     private String accountNo;
   9:     private double balance;
  10:     
  11:     public Account3() {}
  12:     public Account3(String accountNo, double balance) {
  13:         this.accountNo = accountNo;
  14:         this.balance = balance;
  15:     }
  16:     
  17:     public double getBalance() {
  18:         return this.balance;
  19:     }
  20:     
  21:     public void draw(double drawAmount) {
  22:         lock.lock();
  23:         try {
  24:             //             
  25:             if (this.balance >= drawAmount) {
  26:                 //  
  27:                 System.out.println(Thread.currentThread().getName() + "    ,    :" + drawAmount);
  28:                 
  29:                 //    
  30:                 this.balance -= drawAmount;
  31:                 System.out.println("\t   :" + this.balance);
  32:             }
  33:             else {
  34:                 System.out.println("    ,    !");
  35:             }
  36:         } finally {
  37:             lock.unlock();
  38:         }
  39:     }
  40: }