2016-03-21 5 views
3

私はJavaプログラミングの初心者ですが、私はマルチスレッドがJavaの些細な話題ではないことを知っています。また、私はC開発者としてほぼ3年間働いています。異なるオブジェクトのロックでのマルチスレッド

私はこのトピックを読んでいます: "Multiple locks - Behind the scene"と私はそれを完全に理解していますが、私は懸念が1つあります。

Iは次のようにコードを更新します。私は、オブジェクトを作成し、出力される実行メソッドを呼び出し

package multithreading; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class Worker { 

    private List<Integer> list1 = new ArrayList<Integer>(); 
    private List<Integer> list2 = new ArrayList<Integer>(); 

    private Object lock1 = new Object(); 
    private Object lock2 = new Object(); 

    private void updateList1(int i) { 
     synchronized (lock1) { 
      try { 
       Thread.sleep(1); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Worker.class.getName()).log(Level.SEVERE, null, ex); 
      } 
      list1.add(1); 
     } 
    } 

    private void updateList2(int i) { 
     synchronized (lock2) { 
      try { 
       Thread.sleep(1); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Worker.class.getName()).log(Level.SEVERE, null, ex); 
      } 
      list2.add(1); 
     } 
    } 

    public void process(int ii) { 
     for (int i = 0; i < 1000; i++) { 
      updateList1(ii); 
      updateList2(ii); 
     } 
    } 

    public void execute() { 
     Thread t1 = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       process(1); 
      } 
     }); 

     Thread t2 = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       process(2); 
      } 
     }); 

     long start = System.currentTimeMillis(); 

     t1.start(); 
     t2.start(); 

     try { 
      t1.join(); 
      t2.join(); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(Worker.class.getName()).log(Level.SEVERE, null, ex); 
     } 

     long end = System.currentTimeMillis(); 

     System.out.println("Time taken: " + (end - start)); 
     System.out.println("List1: " + list1.size() + "; list2: " + list2.size()); 
    } 
} 

メインクラス:

Time taken: 2186 List1: 2000; list2: 2000

しかし、私は両方を行った場合を関数(updateList1、updateList2)は​​であり、lock1lock2のメッセージを削除しました

主意志出力:懸念が​​コールupdateList1()次いでupdateList2()内部コードであるスレッドが取得した場合

Time taken: 4342 List1: 2000; list2: 2000

は、それが(​​ブロックを使用して)最初のコードでは、両方の方法のために逐次求めていますlock1と他のスレッドがupdateList1()を呼び出そうとすると、もう1つのスレッドによってlock1が解放されるのを待つことになります。そのため、両方の実装方法で時間が同等でなければなりません。

私はJavaで誤って何かを理解している場合、このシナリオでは、私はC.

答えて

2

同期メソッドでは、両方のメソッドのどちらか一方のみを任意の時点で実行できます。これは、次の(他の多くの可能性があり、もちろん)などのシーケンシャルな実行につながる:

t1: updateList1    updateList2 
t2:    updateList1    updateList2 

代わりに別のロックオブジェクトの同期ステートメントを使用して、両方の方法を同時に実行することができます。

t1: updateList1 updateList2 updateList1 updateList2 
t2:    updateList1 updateList2 updateList1 
初期ステップ updateList1

updateList2を並列に実行することができます。メソッドは同じ時間量を必要とするため、2番目のケースで理想的な2倍のスピードアップが得られます。

1

の私の経験から知っているので、場合にあなたがupdateList1を作るところからの時間が、同じではありません答えと申し訳ありませんがcalrifyしてくださいし、 updateList2は、ロックインスタンスとしてWorkerオブジェクトを使用します。

したがって、1つのスレッドがupdateList2を実行している場合、もう1つのスレッドはupdateList1を入力できません。

1
  • ロックされたオブジェクト が異なるため、最初のケースではロックが適用されません。
  • 2番目の場合、ロックオブジェクト を削除すると、lockオブジェクトはTestのインスタンスになります。 にはlist1とlist2が含まれています。その場合、Testの同期が にThread1によってアクセスされているとき、Thread2は待機し、そしてvicevesaを待つ必要があります。
関連する問題