Javaマルチスレッド同期Synchronizedクラスオブジェクトとクラスインスタンスオブジェクトを深く解析

10753 ワード


    
同期の概念:
同期は、同期方法と同期ブロックの2つの方法に分けられる.
ロックされた内容は、ロックされたクラスの特定のインスタンスとロックされたクラスオブジェクト(クラスのすべてのインスタンス)に分けられます.
変数は、インスタンス変数(staticを持たない変数)とクラス変数(staticを持つ変数)に分けられます.
同期の使用理由
1.システム内で訪問クラスに対してマルチスレッドを使用してアクセスする;
2.クラスにクラス変数があるか、クラスのメソッドに共通リソース(外部ファイルの読み書きなど)にアクセスしている.
同期ロックロックの内容は何ですか?
メソッドの前にSynchronizedを追加しても、変数の前に追加しても、ロックされているのはクラスオブジェクトです.各オブジェクトには、ロックが1つしか関連付けられていません.
次の例では、状況別に様々な場合の同期効果を列挙する
1.Synchronizedをメソッドに追加します(同期メソッド、ロッククラスインスタンス)
Javaコード
 public class Demo1 {         
    public synchronized void m1(){             //...............   
  }     
    public void m2(){            //............     
synchronized(this){//......Javaマルチスレッド同期Synchronizedの詳細解析
}   //........     

    }    
 
この2つの書き方の効果は同じで、ロックされているのはクラスインスタンスオブジェクトです.クラスインスタンスオブジェクト:demo=new Demo 1()と、thread 1,thread 2の2つのスレッドがdemoオブジェクトを呼び出す場合、同じ時間にthread 1がdemoを呼び出す.m 1()の場合、thread 2はその時間内にdemoにアクセスできない.m 1()とdemo.m2(); thread 1はdemoというオブジェクトのロックを使用しているので、他のスレッドに分けて使用することはできません
ただし、thread 1がdemo 1を呼び出すと.m 1()、thread 2はdemo 2を呼び出す.m 1()は、異なるDemo 1クラスのオブジェクトインスタンスを呼び出すため、同時に実行できます.
2.変数にSynchronizedを追加します(同期ブロック、ロッククラスインスタンス)
Javaコード
 

   
   
   
   
  1. public class Demo2 {     
  2.     Object a = new Object();     
  3.     Object b = new Object();     
  4.     
  5.     public void m1(){     
  6.         //............     
  7.     
  8.         synchronized(a){     
  9.             //.........     
  10.         }     
  11.     
  12.         //........     
  13.     }     
  14.     
  15.     public void m2(){     
  16.         //............     
  17.     
  18.         synchronized(b){     
  19.             //.........     
  20.         }     
  21.     
  22.         //........     
  23.     }     
  24. }    

 
この場合、コードブロックロックが実現され、ロックされたオブジェクトは変数aまたはbである.(a,bともに非static)クラスインスタンスオブジェクト:demo=new Demo 2()と、thread 1,thread 2の2つのスレッドがdemoオブジェクトを呼び出す場合、同じ時間にthread 1がdemoを呼び出す.m 1()の場合、thread 2はその時間内にdemoにアクセスできる.m2();しかしdemoにアクセスできません.m 1()の同期ブロックは、aがthread 1によってロックされているためである.
3.Synchronizedはクラス変数、すなわちstatic変数(属性、メソッド)をロックします(クラスオブジェクトをロックします).
Javaコード
 

   
   
   
   
  1. public class Demo3 {     
  2.     static Object o = new Object();     
  3.     
  4.     public static synchronized void m1() {     
  5.         //....     
  6.     }     
  7.     
  8.     public static void m2() {     
  9.         //...     
  10.         synchronized (Demo3.class) {     
  11.             //.....     
  12.         }     
  13.         //.....     
  14.     }     
  15.     
  16.     public static void m3() {     
  17.         //..........     
  18.         try {     
  19.             synchronized (Class.forName("Demo3")) {     
  20.               //............     
  21.             }     
  22.         } catch (ClassNotFoundException ex) {     
  23.         }     
  24.         //.............     
  25.     }     
  26.     
  27.     public static void m4() {     
  28.         //............     
  29.        synchronized(o){     
  30.          //........     
  31.        }     
  32.         //..........     
  33.     }     
  34. }    

 
以上の4つの方法では、ロックされたオブジェクトはクラスインスタンスオブジェクトではなくクラスDemo 3であるという効果が得られています.すなわち、マルチスレッドでは、共有されているリソースはクラスオブジェクトではなく、クラスオブジェクトに属しています.この場合、thread 1がこの4つのメソッドのいずれかにアクセスした場合、同じ時間に他のスレッドはこの4つのメソッドにアクセスできません.
4.クラスのメソッドでは、マルチスレッド共通のリソースにアクセスし、そのリソースは可変であり、この場合も同期が必要である
Javaコード
 

   
   
   
   
  1. public class Demo4 {     
  2.     static String path = "file path";     
  3.     
  4.     public void readConfiFile() {     
  5.         synchronized (path) {     
  6.            //  path 。     
  7.         }     
  8.     
  9.     }     
  10.     
  11.     public void writeConfiFile() {     
  12.         synchronized (path) {     
  13.             // path 。     
  14.         }     
  15.     }     
  16. }    

 
この場合、クラスインスタンスオブジェクトのリソース共有ではなく、変象のリソース共有であるため、クラス変数としてロックする必要があります.
成也スレッド、敗也スレッドは、うまく使えば性能を向上させ、うまく使えないとシステムの後患が尽きない.
PS:スレッド同期を行うには大きなシステムオーバーヘッドが必要なので、使用時に必要でない場合は、できるだけ同期機能を使用しない.