JAva内部ロックと同期メカニズム
2571 ワード
Sychronizedは、内部ロックまたは監視ロックと呼ばれる内部コンポーネントから構成される.内部ロックはsychronizedの2つの側面で機能し、1つのオブジェクトの状態に強制的に個別にアクセスし、各sychronizedメソッドにhappen-before関係を確立する.
各オブジェクトには内部ロックが関連付けられています.従来、各スレッドは、オブジェクトにアクセスする際に、オブジェクトのプロパティを個別に一貫して取得する必要があります.このオブジェクトにアクセスする前に内部ロックを取得し、アクセスが終了した後に解放します.スレッドが内部ロックの中間を取得して解放すると,スレッドがこの内部ロックを保持していると呼ぶ.1つのスレッドが内部ロックを持っている場合、他のスレッドはこの内部ロックにアクセスできず、アクセスしようとするとブロックされます.
1つのスレッドが内部ロックを解放すると、1つのhappen-before関係は、この動作と次の任意のこのロックの次の取得動作とで確立される.
sychronized文
もう1つのsychronized符号化を作成する方法はsychronized文を使用することです.sychronized法とは異なり、sychronized文が指定するオブジェクトには内部ロックが必要です.public void addName(String name){synchronized(this){lastName=name;nameCount++;}nameList.add(name); } この例では、addnameというメソッドはlastnameとnamecount変数を並列に変更するとともに、他のオブジェクトのメソッド呼び出し(他のオブジェクトを呼び出すメソッドがアクティブな問題を引き起こす可能性がある)がsychronized文がなければここでは分離されることを防止する必要がある.sychronizedメソッドがなければ、唯一の目的はnamelist.addメソッドを呼び出すことである.
Sychronized文は、細粒度を実現するsychronized化に対して並列化される.たとえば、栗を挙げると、クラスMsLunchには2つのインスタンスフィールドc 1とc 2があり、一緒に使用されたことはありません.この2つのフィールドの更新は同期化する必要があるが、c 1の更新とc 2の更新が交互に実行できないという理由はなく、同時発生による不要なブロックを低減することができる.同期メソッドやこれに関連付けられた他のロックメカニズムではなく、2つのオブジェクトにロックを提供するように作成しました.public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object();
}このメカニズムを使用するには、交互に更新するときにエラーが発生しないことを確認する必要があります.1つのスレッドを同期しても、別のスレッドが占有するロックを取得できません.しかし、1つのスレッドは、再同期と呼ばれる自分のスレッドが占有するロックを取得することができます.これは、同期コードが直接的または非直接的に1つのSynchronizedも含むコードを実行し、2つのコードセットが同じロックである場合を記述する.同期文への繰り返しアクセスに加えて、同期コードは、自身がブロックされるのを防ぐために多くの措置を取らなければなりません.
Atomic accessは,符号化時に原子アクセスが有効な操作トランザクションである.原子動作は半分まで実行されると停止しません.完了するか、完了しないかです.原子操作が完了するまで何の現象も見えません.c++のような成長式を見たことがあるが,原子操作と見なすことはできない.短い式でも複数のサブオペレーションに分解できます.しかし、これらの動作は原子的であると言える:1.参照変数とほとんどの組み込み変数(longとdoubleを除く)の読み書き操作;2.volatileで宣言された変数(longとdoubleを含む)の読み書き操作.原子間操作が交差しないため、スレッドの競合を心配する必要はありません.しかし、原子間操作をすべて除去する必要はありません.sychronized操作も必要です.メモリ整合性の問題が発生する可能性があります.volatile変数を使用すると、volatile変数を書き込むと、volatile変数がメモリ整合性エラーのリスクを低減できます.の方法では、後続の読み取り操作とhappen-before関係が確立されます.これは、volatile変数に対するすべての操作が他のスレッドに対して可視であることを示します.さらに重要なのは、volatileの変数を読み取ると、最後の変化だけでなく、それを変えることができることを意味します.簡単なvolatile変数を使用するとsychronizedメカニズムを使用して同期するよりも便利ですが、メモリの一貫性がエラーになる可能性があることにも注意してください.このようなことをする必要があるかどうかは、あなたが適用する大きさと複雑さにかかっています.java.util.concurrentパッケージにはsychronizedメカニズムに依存しない原子操作を用いたクラスがいくつかあり、High Level Concurrency Objectsという節でこれらの問題を議論する.
各オブジェクトには内部ロックが関連付けられています.従来、各スレッドは、オブジェクトにアクセスする際に、オブジェクトのプロパティを個別に一貫して取得する必要があります.このオブジェクトにアクセスする前に内部ロックを取得し、アクセスが終了した後に解放します.スレッドが内部ロックの中間を取得して解放すると,スレッドがこの内部ロックを保持していると呼ぶ.1つのスレッドが内部ロックを持っている場合、他のスレッドはこの内部ロックにアクセスできず、アクセスしようとするとブロックされます.
1つのスレッドが内部ロックを解放すると、1つのhappen-before関係は、この動作と次の任意のこのロックの次の取得動作とで確立される.
sychronized文
もう1つのsychronized符号化を作成する方法はsychronized文を使用することです.sychronized法とは異なり、sychronized文が指定するオブジェクトには内部ロックが必要です.public void addName(String name){synchronized(this){lastName=name;nameCount++;}nameList.add(name); } この例では、addnameというメソッドはlastnameとnamecount変数を並列に変更するとともに、他のオブジェクトのメソッド呼び出し(他のオブジェクトを呼び出すメソッドがアクティブな問題を引き起こす可能性がある)がsychronized文がなければここでは分離されることを防止する必要がある.sychronizedメソッドがなければ、唯一の目的はnamelist.addメソッドを呼び出すことである.
Sychronized文は、細粒度を実現するsychronized化に対して並列化される.たとえば、栗を挙げると、クラスMsLunchには2つのインスタンスフィールドc 1とc 2があり、一緒に使用されたことはありません.この2つのフィールドの更新は同期化する必要があるが、c 1の更新とc 2の更新が交互に実行できないという理由はなく、同時発生による不要なブロックを低減することができる.同期メソッドやこれに関連付けられた他のロックメカニズムではなく、2つのオブジェクトにロックを提供するように作成しました.public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}このメカニズムを使用するには、交互に更新するときにエラーが発生しないことを確認する必要があります.1つのスレッドを同期しても、別のスレッドが占有するロックを取得できません.しかし、1つのスレッドは、再同期と呼ばれる自分のスレッドが占有するロックを取得することができます.これは、同期コードが直接的または非直接的に1つのSynchronizedも含むコードを実行し、2つのコードセットが同じロックである場合を記述する.同期文への繰り返しアクセスに加えて、同期コードは、自身がブロックされるのを防ぐために多くの措置を取らなければなりません.
Atomic accessは,符号化時に原子アクセスが有効な操作トランザクションである.原子動作は半分まで実行されると停止しません.完了するか、完了しないかです.原子操作が完了するまで何の現象も見えません.c++のような成長式を見たことがあるが,原子操作と見なすことはできない.短い式でも複数のサブオペレーションに分解できます.しかし、これらの動作は原子的であると言える:1.参照変数とほとんどの組み込み変数(longとdoubleを除く)の読み書き操作;2.volatileで宣言された変数(longとdoubleを含む)の読み書き操作.原子間操作が交差しないため、スレッドの競合を心配する必要はありません.しかし、原子間操作をすべて除去する必要はありません.sychronized操作も必要です.メモリ整合性の問題が発生する可能性があります.volatile変数を使用すると、volatile変数を書き込むと、volatile変数がメモリ整合性エラーのリスクを低減できます.の方法では、後続の読み取り操作とhappen-before関係が確立されます.これは、volatile変数に対するすべての操作が他のスレッドに対して可視であることを示します.さらに重要なのは、volatileの変数を読み取ると、最後の変化だけでなく、それを変えることができることを意味します.簡単なvolatile変数を使用するとsychronizedメカニズムを使用して同期するよりも便利ですが、メモリの一貫性がエラーになる可能性があることにも注意してください.このようなことをする必要があるかどうかは、あなたが適用する大きさと複雑さにかかっています.java.util.concurrentパッケージにはsychronizedメカニズムに依存しない原子操作を用いたクラスがいくつかあり、High Level Concurrency Objectsという節でこれらの問題を議論する.