0。パイオニア質問コード
次のコードは、2つのスレッドが同時にiを蓄積するカウンターを示しており、それぞれが1000,000回実行されます。予想される結果は、間違いなくi = 2000000です。ただし、何度も実行した後、私の値は常に2000000未満になることがわかります。これは、2つのスレッドが同時に私を書くと、1つのスレッドの結果が他のスレッドを上書きするためです。
public class Accountingsyncは実行可能{static int i = 0; public void crossion(){i ++; } @Override public void run(){for(int j = 0; j <1000000; j ++){result(); }} public static void main(string [] args)throws arturnedexception {AccountingSync AccountingSingsync = new Accountingsync();スレッドT1 =新しいスレッド(AccountIngingSync);スレッドT2 =新しいスレッド(AccountingSync); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }}この問題を根本的に解決するには、iを操作するときに複数のスレッドを完全に同期する必要があることを確認する必要があります。つまり、スレッドAが私を書き込むとき、スレッドBは書くことができないだけでなく、それを読むこともできません。
1。同期されたキーワードの役割
同期されたキーワードの機能は、実際にスレッド間の同期を実現することです。その仕事は、同期コードをロックして、1つのスレッドのみが一度に同期ブロックに入ることができるようにすることです。これにより、スレッド間のセキュリティが保証されます。上記のコードと同様に、I ++操作は同時に別のスレッドによってのみ実行できます。
2.同期されたキーワードの使用
オブジェクトロックを指定します:指定されたオブジェクトをロックし、同期コードブロックを入力して、指定されたオブジェクトのロックを取得します
インスタンスメソッドに直接作用する:現在のインスタンスをロックすることと同等です。同期コードブロックを入力すると、現在のインスタンスのロックを取得する必要があります(これには、スレッドを作成するときに同じ実行可能なインスタンスを使用する必要があります)
静的方法に直接作用する:これは、現在のクラスをロックすることと同等です。同期コードブロックを入力する前に、現在のクラスのロックを取得する必要があります。
2.1ロックするオブジェクトを指定します
次のコードは、特定のオブジェクトに同期した適用されます。ここには、指定されたオブジェクトが静的でなければならないことに注意してください。そうしないと、スレッドを新しくするたびにオブジェクトを互いに共有しないため、ロックの意味は存在しなくなります。
public class AccountingSyncは実行可能{final static object = new object();静的int i = 0; public void crossion(){i ++; } @Override public void run(){for(int j = 0; j <1000000; j ++){synchronized(object){result(); }}} public static void main(string [] args)throws arturtedexception {thread t1 = new swerch(new Accountingsync());スレッドT2 = newスレッド(new AccountingSync()); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }} 2.2インスタンスメソッドに直接動作します
同期されたキーワードは、インスタンスメソッド、つまり、増加()メソッドを入力する前に、スレッドが現在のインスタンスのロックを取得する必要があります。これには、スレッドインスタンスを作成するときに同じ実行可能なオブジェクトインスタンスを使用する必要があります。それ以外の場合、スレッドのロックは同じインスタンスにないため、ロック/同期の問題について話す方法はありません。
public class Accountingsyncは実行可能{static int i = 0; public同期void増加(){i ++; } @Override public void run(){for(int j = 0; j <1000000; j ++){result(); }} public static void main(string [] args)throws arturnedexception {AccountingSync AccountingSingsync = new Accountingsync();スレッドT1 =新しいスレッド(AccountIngingSync);スレッドT2 =新しいスレッド(AccountingSync); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }}インスタンスメソッドのキーワードの正しい使用法を説明するために、メインメソッドの最初の3行に注意してください。
2.3静的方法に直接作用します
同期されたキーワードを静的メソッドに適用するには、2つのスレッドを使用して上記の例と同じ実行可能な方法を指す必要はありません。メソッドブロックは、現在のインスタンスではなく現在のクラスのロックを要求する必要があるため、スレッドは正しく同期することができます。
public class Accountingsyncは実行可能{static int i = 0; public static同期void増加(){i ++; } @Override public void run(){for(int j = 0; j <1000000; j ++){result(); }} public static void main(string [] args)throws arturnedexception {thread t1 = new swerch(new Accountingsync());スレッドT2 = newスレッド(new AccountingSync()); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }}3.誤ったロック
上記の例から、カウンターアプリケーションが必要な場合、データの正確性を確保するために、当然カウンターをロックする必要があるため、次のコードを書くことができることがわかります。
パブリッククラスBADLOCKONINTEGERは実行可能{Static Integer i = 0; @Override public void run(){for(int j = 0; j <1000000; j ++){synchronized(i){i ++; }}} public static void main(string [] args)arturtedexception {badlockoninteger badlockoninteger = new badlockoninteger();スレッドT1 =新しいスレッド(badlockoninteger);スレッドT2 =新しいスレッド(badlockoninteger); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }}上記のコードを実行すると、出力Iが非常に小さいことがわかります。これは、スレッドが安全ではないことを意味します。
この問題を説明するには、整数から始める必要があります。Javaでは、整数は不変のオブジェクトです。文字列のように、オブジェクトが作成されると、変更できません。整数= 1を持っている場合、それは常に1になります。このオブジェクト= 2が必要な場合はどうなりますか?整数のみを再現できます。各I ++の後、整数のValue Of Methodを呼び出すことと同等です。 IntegerのValueof Methodのソースコードを見てみましょう。
public static integer valueof(int i){if(i> = integercache.low && i <= integercache.high)return integercache.cache [i +(-integercache.low)];新しい整数(i);}を返しますinteger.valueof()は実際にはファクトリーメソッドであり、新しい整数オブジェクトを返し、値をiにコピーする傾向があります。
したがって、問題の理由を知っています。複数のスレッドの間では、I ++がIの後に来るため、新しいオブジェクトを指すため、スレッドはロックされるたびに異なるオブジェクトインスタンスをロードする場合があります。ソリューションは非常にシンプルです。上記の3つの同期メソッドのいずれかを使用して、解決できます。