2016-03-21 20 views
3

Java programında yeni bir kullanıcıyım ve Multithreading'in Java'da önemsiz bir konu olmadığını biliyorum. Ayrıca neredeyse 3 yıldır C geliştiricisi olarak çalışıyorum.Farklı nesnelerin kilidinin okunması

Bu konuyu okudum: "Multiple locks - Behind the scene" ve tamamen anlıyorum ama bir endişem var.

ben aşağıdaki gibi kod güncelleme: Ben bir nesne oluşturulur ve çıkışı yürütmek yöntemi denilen

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()); 
    } 
} 

Ve ana sınıfında:

Time taken: 2186 List1: 2000; list2: 2000

Ancak hem yaptıysam işlevleri (updateList1, updateList2) synchronized şeklindedir ve senkronize edilmiş bloğu lock1 ve lock2

ana çıktısı:

Time taken: 4342 List1: 2000; list2: 2000

endişe sonra updateList2() bu nedenle her iki yöntem için sıralı bir arama bir iplik elde edilen, ilk kod (synchronized blok kullanılarak), bir execute() aramaları updateList1() içindeki kod lock1 ve updateList1() numaralı telefonu aramaya çalışan diğer iş parçacığı, diğer iş parçacığı tarafından lock1 yayımlanmasını bekler. Yani zaman, her iki uygulama biçiminde de eşdeğer olmalıdır.

ben yanlış Java şey anlamak eğer updateList1 yapmak ve nerede bu senaryo durumunda beri, C

cevap

2

Senkronize yöntemlerle, her iki yöntemden yalnızca biri herhangi bir zamanda yürütülebilir. Bu aşağıdaki (tabi orada bir çok diğer olasılıklar) gibi sıralı olarak gerçekleştirilmesine yol açar: yerine farklı kilit nesnelerde senkronize ifadeleri kullanma

t1: updateList1    updateList2 
t2:    updateList1    updateList2 

, her iki yöntem aynı anda çalışmasını sağlar.

t1: updateList1 updateList2 updateList1 updateList2 
t2:    updateList1 updateList2 updateList1 
ilk adım updateList1 sonra

ve updateList2 paralel çalışır. Yöntemler aynı miktarda zaman gerektirdiğinden, ikinci durumda da ideal bir hızlanma 2 elde edersiniz. İlk durum için

1

zaman benim deneyimlerinden bildiklerini aynı değildir, çünkü cevabı ve üzgün calrify Lütfen updateList2 senkronize olarak kilitleme örneği olarak Worker nesnesini kullanırlar.

İkinci durumda, bir iş parçacığı updateList2 çalışıyorsa, diğer iş parçacığı updateList1 giremez.

1
  • , kilitli nesneler fark çünkü uygulanan hiçbir kilit yoktur.
  • İkinci durumunuz için, kilit nesnesini kaldırırsınız, kilit nesnesini şimdi Test'in örneğine gelir, burada list1 ve list2 içerir.Bu durumda, Test'in senkronize edildiği zaman, Thread1 tarafından erişilen olduğu zaman, Thread2'nin beklemesi ve vicevesa olması gerekir.
İlgili konular