Java Learning:同時同期ロック(synchronized)

3618 ワード


引用する
  
最近しばらくの間、実験室はすでに巣立って実習を探して、ブロガーも間に合って、結果は悲しくて喜んで、BAT理の当然のひざまずいて、他のofferも受け取って、総じて基礎を固める必要があると感じています.
ところで、最近javaマルチスレッドを見たとき、スレッドの多くはsynchronized(同期ロック)のキーワードを使っていることがわかり、その理解は「ロック」の概念にとどまっている.ブロガーもsynchronizedを紹介するブログをネットで検索しましたが、見れば見るほどぼんやりしていて、私のレベルはまだ真偽を鑑別できるほどではありません.そこで、「神功を間違え、火をつけて魔に入る」ことを避けるために、私は『Thinking in Java』を捧げました.本文はこの本のsynchronizedに関する内容に対して、いくつかの自分のコード検証を加えて、軽く熟知することができることを求めないで、ただ能力が間違っていないことを求めて、みんなを誤解しないで、もしいくつかの地方に問題があるならば、みんなに許して、意見を指摘してください.
 
同期ロックを使用する理由
  
「Thinking in Java」では、同時作業の場合、2つのタスクが同じリソースにアクセスすることを防止する方法が必要です(実際には共有リソースの競争です). 
この競合を防止する方法は、リソースがタスクによって使用される場合にロックをかけることです.最初にリソースにアクセスするタスクは、他のタスクがロック解除される前にアクセスできないように、リソースをロックする必要があります.ロック解除されると、別のタスクがロックされて使用できます.
 
基本的にすべての同時モードは、スレッド競合の問題を解決する際に、共有リソースへのシーケンス化アクセスを採用するスキームです.これは、所与の時点で1つのタスクのみが共有リソースにアクセスできることを意味し、通常、これはコードの前にロック文を追加することによって実現され、ロック文は相互反発の効果を生じ、このメカニズムは反発量(mutex)と呼ばれる.
 
同期ロックの実現原理?
すべてのオブジェクトには自動的に単一のロック(モニタ)が含まれており、オブジェクトにsynchronizedメソッドを呼び出すと、このオブジェクトはロックされます.
特定のオブジェクトに対して、synchronizedメソッドはすべて同じロックを共有します.
これにより、複数のタスクがオブジェクトメモリに同時にアクセスすることを防止することができる.
特定のオブジェクトに対するすべてのsynchronizedメソッドが同じロックを共有する方法について、重点的に紹介したいと思います.
 
1、2つの同時スレッドが同じオブジェクトobjectのsynchronized(this)同期コードブロックにアクセスすると、1時間に1つのスレッドしか実行できません.別のスレッドは、現在のスレッドがこのコードブロックを実行するまで待たなければなりません.
 
2、あるスレッドがobjectのsynchronized(this)同期コードブロックにアクセスした場合、他のスレッドはobjectの
他のsynchronized(this)同期コードブロックへのアクセスがブロックされます.
 
3、スレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、このobjectのオブジェクトロックが得られる.その結果、objectオブジェクトのすべての同期コード部分への他のスレッドのアクセスが一時的にブロックされる
ポイントが来た!1つのタスクは、オブジェクトのロックを複数回取得できます.1つのメソッドが同じオブジェクト上で2番目のメソッドを呼び出し、後者が同じオブジェクト上の別のメソッドを呼び出した場合に発生します.JVMは、オブジェクトがロックされた回数を追跡し、1つのオブジェクトがロック解除された場合、カウントが0になります.タスクが初めてオブジェクトにロックをかけたとき、カウントは1になります.この同じタスクがこのオブジェクトにロックされるたびに、カウントは増加します.複数のロックの取得を継続できるのは、ロックが最初に取得されたタスクだけであることは明らかです.タスクがsynchronizedメソッドを離れるたびに、カウントは減少し、カウントが0の場合、ロックは完全に解放され、他のタスクはこのリソースを使用することができます.
 
同期ロックはいつ使用しますか?
Brian同期ルール:変数を書いている場合は、次に別のスレッドによって読み込まれるか、前回別のスレッドによって書かれた変数を読み込んでいる場合は、同期を使用し、同じモニタで同期をロックする必要があります.
注意:臨界共有リソースにアクセスする各メソッドは同期されなければなりません.そうしないと、正しく動作しません.
 
同期ロックの使用方法
synchronizedキーワード.synchronizedメソッドとsynchronizedブロックの2つの使い方が含まれます. 
  • synchronizedメソッド:
  • public synchronized void countNum(int n); 
    

    特定のオブジェクトのすべてのsynchronizedメソッドは、同じロックを共有します.このメカニズムは、synchronizedとして宣言されたすべてのメンバー関数のうち、実行可能な状態にあるのは1つだけです(クラスのインスタンスに対応するロックが1つしか得られないため).これにより、クラスメンバー変数にアクセスできるすべてのメソッドがsynchronizedとして宣言される限り、クラスメンバー変数のアクセス競合を効果的に回避できます. 
    それだけでなく、静的メソッドをsynchronizedとして宣言して、クラスの静的メンバー変数へのアクセスを制御することもできます.
    public static synchronized void countNum(int n); 
    

    synchronizedメソッドの欠陥:大きなメソッドをsynchronizedと宣言すると、効率に大きく影響します.
    典型的には、スレッドクラスのメソッドrun()をsynchronizedと宣言すると、スレッドのライフサイクル全体で実行されるため、このクラスのsynchronizedメソッドの呼び出しは成功しません.もちろん、クラスメンバー変数にアクセスするコードを特定のメソッドに配置してsynchronizedと宣言し、メインメソッドで呼び出すことでこの問題を解決することができますが、Javaはsynchronizedブロックというより良い解決策を提供しています.
     
  • synchronizedブロック:
  • synchronized(SyncObject.Class) {  
        //           
    }  
    

    次のように書くこともできます.thisは、現在のクラスを指します.
    synchronized(this) {  
        //           
    }  
    

    synchronizedブロックは、前述したようにクラスインスタンスまたはクラスであってもよいオブジェクトsyncObjectのロックを取得しなければならないコードブロックであり、具体的なメカニズムは前述したとおりである.任意のコードブロックに対して、ロックされたオブジェクトを任意に指定できるため、柔軟性が高い.
    synchronizedブロックを使用する場合は、Brian同期規則に従い、臨界共有リソースにアクセスする方法ごとに同期する必要があります.
     
     
     
     
     
    転載先:https://www.cnblogs.com/danbing/p/5319820.html