この記事では、JAVA マルチスレッドのオブジェクト ロックとしての synchronized キーワードに関するいくつかの知識ポイントを紹介します。
いわゆるオブジェクトロックとは、オブジェクトを同期的にロックすることを意味します。オブジェクトのロックについては、こちらの記事を参照してください。
1. 分析
synchronized は、次の形式でインスタンス メソッドを変更できます:
public class MyObject { synchronized public void methodA() { //do something.... }
ここで、synchronized キーワードは現在のオブジェクトをロックします。これがオブジェクト ロックと呼ばれる理由でもあります。
現在のオブジェクトをロックする理由は何ですか? MethodA() はインスタンス メソッドであるため、methodA() を実行する場合は、object.method() (obj.methodA() の形式で呼び出す必要があります。obj は MyObject クラスのオブジェクトです。同期ロックオブジェクトobj)。
上記のコードは次のように書くこともできます:
public class MyObject { public void methodA() { synchronized(this){ //do something.... } }
2. 特徴
synchronized キーワードを使用して同期することの明らかな特徴は次のとおりです: MyObject クラスで複数の同期された変更インスタンス メソッドが定義されている場合、マルチスレッド 同じ MyObject クラスのオブジェクトの場合、これらのメソッドは同期的にのみ実行できます。つまり、同期変更メソッドを実行した後、別の同期変更メソッドを実行できます。
次のように:
public class MyObject { synchronized public void methodA() { //do something.... } synchronized public void methodB() { //do some other thing } }
MyObject クラスには 2 つの同期された変更メソッドがあります。
public class ThreadA extends Thread { private MyObject object; //省略构造方法 @Override public void run() { super.run(); object.methodA(); } }
スレッドAはmethodA()を実行します
public class ThreadB extends Thread { private MyObject object; //省略构造方法 @Override public void run() { super.run(); object.methodB(); } }
スレッドBはmethodB()を実行します
public class Run { public static void main(String[] args) { MyObject object = new MyObject(); //线程A与线程B 持有的是同一个对象:object ThreadA a = new ThreadA(object); ThreadB b = new ThreadB(object); a.start(); b.start(); } }
スレッドAとスレッドBはMyObjectクラスの同じオブジェクトを保持していますが、この2つはたとえば、スレッド B は、メソッド B() メソッドを実行する前に、スレッド A がメソッド A() メソッドの実行を完了するまで待機する必要があります。
3. 結論
上記からわかるように、この記事で説明する同期ロックの範囲はオブジェクト全体です。クラス内に同期された変更された同期メソッドが複数あり、複数のスレッドがクラスの同じオブジェクト (クラスの同じオブジェクト) を保持している場合、それらが異なるメソッドを呼び出している場合でも、各メソッドの実行も同期されます。
同期されたメソッド間に共有変数がない場合、またはメソッド間に接続がないが同期的にのみ実行できる場合、効率に影響します。
4. アプリケーション - データの不整合によるダーティデータの読み取りを避けるために同期を使用します。
次の例:
public class MyObject { private String userName = "b"; private String passWord = "bb"; synchronized public void methodA(String userName, String passWord) { this.userName = userName; try{ Thread.sleep(5000); }catch(InterruptedException e){ } this.passWord = passWord; } synchronized public void methodB() { System.out.println("userName" + userName + ": " + "passWord" + passWord); } }
methodA() はユーザー名とパスワードを変更します。実際には、ユーザー名はパスワードに対応します。
methodB() はユーザー名とパスワードを読み取る役割を果たします。
methodB()がsynchronizedで変更されていない場合、スレッドAはmethodA()を呼び出して7行目まで実行し、ユーザー名を変更し、何らかの理由(9行目でスリープしているなど)でCPUを放棄します。
この時、スレッドBがmethodB()を実行すると、読み込まれるユーザー名はスレッドAが変更したユーザー名("a")となりますが、パスワードは元のパスワード("bb")となります。スレッド A がスリープ状態になり、パスワードを変更する時間がなかったためです。
ただし、methodB() が synchronized で変更された場合、スレッド B は、メソッド B を実行してユーザー名とパスワードを読み取る前に、スレッド A の実行が完了する (つまり、ユーザー名とパスワードが変更される) まで待機することしかできません。したがって、データの不整合によって引き起こされるダーティ リードの問題が回避されます。
以上がこの記事の全内容です。Java プログラミングを学習する皆さんのお役に立てれば幸いです。
Java マルチスレッド プログラミングの Synchronized キーワードの詳細な説明と関連記事については、PHP 中国語 Web サイトに注目してください。