Javaでの同期:何を、どのように、そしてなぜ?



Javaでの同期に関するこの記事は、マルチスレッドプログラムの同期について学習する方法をガイドするのに役立ちます。

マルチスレッドプログラムは、複数の状況を定期的に思い付く可能性があります 詐欺的で驚くべき結果を生み出す同じリソースに到達しようとします。これは、Javaの同期を使用することで解決できます。特定の1つのスレッドだけが、特定の時間の目的でリソースに到達できます。この記事は、同期戦略を理解するのに役立ちます。

トピックについて次の順序で説明します。





始めましょう!

Javaで同期を使用する理由



プログラム内で少なくとも2つのスレッドから開始する場合、複数のスレッドが同じリソースにアクセスしようとする可能性があります。並行性の問題のために、予期しない結果が生じることさえあります。

構文

synchronized(objectidentifier){//共有変数およびその他の共有リソースにアクセスする}

例えば、 同等のファイル内に書き込もうとします。スレッドの1つがデータをオーバーライドする可能性があるため、またはスレッドが開いているときに、これによりデータが破損する可能性があります。同じファイルを同時に、別のスレッドが同じファイルを閉じている可能性があります。複数のスレッドのアクションを同期する必要があります。これは、と呼ばれる概念を使用して実装できます M onitors



  • 各 スレッドがロックまたはロック解除できるモニターに関連付けられています。
  • 一度に1つのスレッドのみがモニターのロックを保持できます。
  • Java プログラミング言語は、スレッドを作成し、それらのタスクを同期するための非常に便利な方法を提供します。 同期 ブロック。
  • また、共有リソースをこの特定のブロック内に保持します。

Javaで同期されたブロックは、 同期 キーワード。 Javaのこのブロックは、いくつかのオブジェクトで同期されます。同じオブジェクトで同期されているすべてのブロックは、一度に1つのスレッドのみを実行できます。同期ブロックに入ろうとする他のすべてのスレッドは、同期ブロック内のスレッドがブロックを出るまでブロックされます。

同期の種類

利用可能な同期には基本的に2つのタイプがあります。彼らです:

  1. プロセスの同期: 複数のスレッドまたはプロセスを同時に実行して、特定の一連のアクションにコミットするような状態に到達します。
  2. スレッドの同期: 複数のスレッドがある場合共有リソースにアクセスしようとすると、リソースが次の1つのスレッドでのみ使用されるようにする必要があります。時間。

これらのタイプの詳細には触れず、ロックインとは何かを理解しようとしないでください

Javaでのロック

先に述べたように、同期は、 ロック または モニター 。すべてのオブジェクトには、ロックが関連付けられています。したがって、オブジェクトのフィールドへの一貫したアクセスが必要なスレッドは、オブジェクトにアクセスする前にオブジェクトのロックを取得し、作業が完了したらロックを解放する必要があります。

Javaの文字とは何ですか

Java 5以降、パッケージjava.util.concurrent.locksには多くのロック実装が含まれています。

ロックは次のようになります。

public class Lock {private boolean isLocked = false public synchronized void lock()throws InterruptedException {while(isLocked){wait()} isLocked = true} publicsynchronized voidunlock(){isLocked = false notify()}}

lock()メソッドはLockインスタンスをロックして、lock()を呼び出すすべてのスレッドがunlock()が実行されるまでブロックされるようにします。

同期なしのマルチスレッド

これは、カウンター値をシーケンスで出力する簡単な例であり、実行するたびに、スレッドに対するCPUの可用性に基づいて異なる結果が生成されます。これをチェックしてください!

クラスマルチスレッド{publicvoid printCount(){try {for(int i = 5 i<0 i--) { System.out.println('Counter --- ' + i ) } } catch (Exception e) { System.out.println('Thread interrupted.') } } } class Thread extends Multithread { private Thread t private String threadName Multithread MT Thread( String name, Multithread mt) { threadName = name MT= mt } public void run() { MT.printCount() System.out.println('Thread ' + threadName + ' exiting.') } public void start () { System.out.println('Starting ' + threadName ) if (t == null) { t = new Thread (this, threadName) t.start () } } } public class TestThread { public static void main(String args[]) { Multithread MT = new Multithread() Thread t = new Thread( 'Thread - 1 ', MT) Thread t1 = new Thread( 'Thread - 2 ', MT) t.start() t1.start() // wait for threads to end try { t.join() t1.join() } catch ( Exception e) { System.out.println('Interrupted') } } }

上記のプログラムの結果は次のとおりです。

c ++は名前空間を使用します

Javaでの出力同期-Edureka

同期を使用したマルチスレッド

これは上記と同じ例ですが、カウンター値を順番に出力します。実行するたびに、同じ結果が生成されます。

class Multithread {public void printCount(){try {for(int i = 5 i> 0 i-){System.out.println( 'Counter ---' + i)}} catch(Exception e){System。 out.println( 'Threadinterrupted。')}}} class Thread extends Multithread {private Thread t private String threadName Multithread MT Thread(String name、Multithread mt){threadName = name MT = mt} public void run(){synchronized( MT){MT.printCount()} System.out.println( 'Thread' + threadName + 'exiting。')} public void start(){System.out.println( 'Starting' + threadName)if(t == null){t = new Thread(this、threadName)t.start()}}} public class TestThread {public static void main(String args []){Multithread MT = new Multithread()Thread T = new Thread( 'Thread --1 '、MT)スレッドT1 = new Thread('スレッド-2 '、MT)T.start()T1.start()//スレッドが終了するのを待つtry {T.join()T1.join()} catch(Exception e){System.out.println( 'Interrupted')}}}

出力を以下に示します。

同期されたキーワード

同期されたキーワード ブロックまたはメソッドをクリティカルセクションとしてマークします。クリティカルセクションとは、一度に1つのスレッドのみが実行され、スレッドが同期セクションのロックを保持することです。この 同期 キーワードは書くのに役立ちます 同時 アプリケーションの一部。また、ブロック内の共有リソースも保護します。

同期キーワードは、次のコマンドで使用できます。

コードブロックについて説明しましょう。

同期されたキーワード:コードブロック

構文

同期ブロックを作成するための一般的な構文は次のとおりです。

同期(lockObject){//同期されたステートメント}

スレッドがブロック内で同期されたステートメントを実行する場合、lockObjectのモニターでロックを取得する必要があります。一度に1つのスレッドのみがロックオブジェクトのモニターを取得できます。したがって、他のすべてのスレッドは、現在実行中のスレッドがロックを取得して実行を終了するまで待機する必要があります。
このように、 同期 キーワードは、一度に1つのスレッドのみが同期ブロックステートメントを実行することを保証し、したがって、複数のスレッドがブロック内に存在する共有データを破壊するのを防ぎます。

注意

  • スレッドがスリープ状態になった場合( 睡眠() メソッド)その後、ロックを解除しません。このスリープ時間中、同期されたブロックステートメントを実行しているスレッドはありません。
  • Java同期はスローします NullPointerException ‘で使用されるロックオブジェクトの場合 同期(ロック) ' 無効です。

それでは、その方法について説明しましょう。

同期されたキーワード: 方法

構文

を書くための一般的な構文 同期方式 は:

Javaの数値の桁の合計
同期メソッド(パラメーター){//同期コード}

ここに lockObject 同期されたステートメントを表すモニターにロックが関連付けられているオブジェクトへの単なる参照です。

同期ブロックと同様に、スレッドは、同期メソッドを使用して、接続されたモニターオブジェクトのロックを取得する必要があります。同期メソッドの場合、ロックオブジェクトは次のとおりです。

  • 「.class」オブジェクト –指定されたメソッドが 静的
  • 「この」オブジェクト –メソッドが 非静的 。 「this」は、同期メソッドが呼び出される現在のオブジェクトへの参照です。

Java同期キーワードは 再入可能 本来は。つまり、同期メソッドが同じロックを必要とする別の同期メソッドを呼び出すと、ロックを保持している現在のスレッドは、ロックを取得せずにそのメソッドに入ることができます。

この記事の最後のトピックに進み、同期されたキーワードと同期ブロックの主な違いを指摘しましょう。

同期キーワードと同期ブロックの違い

  • 同期キーワードを使用する場合 方法 、メソッド全体のオブジェクトのロックを取得します。これは、呼び出された現在のスレッドが実行を終了するまで、他のスレッドが同期メソッドを使用できないことを意味します。
  • 同期 ブロック 同期キーワードが指定された後、括弧の間でのみオブジェクトのロックを取得します。これは、ブロックが終了するまで、他のスレッドがすでにロックされているオブジェクトのロックを取得できないことを意味します。ただし、他のスレッドは、メソッドに存在する残りのコードにアクセスできます。

これでこの記事の終わりになり、Javaでの同期がどのように正確に機能するかについて説明しました。このチュートリアルで共有されているすべてのことを明確に理解してください。

チェックしてください 25万人以上の満足した学習者のネットワークを持つ信頼できるオンライン学習会社であるEdurekaが世界中に広がっています。私たちはあなたの旅のあらゆるステップを支援するためにここにいます。このJavaインタビューの質問に加えて、Java開発者になりたい学生や専門家向けに設計されたカリキュラムを考え出します。

質問がありますか?この「Javaでの同期」のコメントセクションで言及してください。 「」 記事と私たちはできるだけ早くあなたに返信します。