運行

2016-11-17 52 views
0

有時varible總將等於別的東西,而不是在運行時的50005000這是百達短樣50005001時,有時會跑,爲什麼會出現這種情況應該不同步(本)創建一個鎖可以當爲什麼我得到這個方法的不一致只有在線程釋放鎖後才能更新?運行

import java.util.concurrent.atomic.AtomicLong; 

public class CurrentThread { 
    public static AtomicLong c = new AtomicLong(0L); 
    public static AtomicLong total = new AtomicLong(0L); 
    public static void main(String[] args) { 

     Thread t = Thread.currentThread(); 
     System.out.println(t); 
     t.setName("My Thread"); 
     System.out.println(t); 

     for (int x = 0; x < 10; x++) { 
      System.out.println("Instance " + x); 
      new Thread(new Updater(x, "Thread: " + String.valueOf(x))).start(); 
     } 
     try { 
      Thread.sleep(1000); 
     } 
     catch (InterruptedException e) { 
     }  
    } 
} 
class Updater implements Runnable { 
    public int na; 
    private String threadName; 
    public Updater(int n, String threadName) { 
     this.na = n; 
     this.threadName = threadName; 
    } 
    @Override 
    public void run() { 
     this.updateCount(); 
     if(CurrentThread.total.get() == 50005000) { 
      System.out.println("Passed"); 
     } 
     else { 
      System.out.println("Failed"); 
     } 
    }  
    public void updateCount() { 

      while (CurrentThread.c.get() < 10000) { 
       synchronized(this) { 
        CurrentThread.c.getAndIncrement(); 
        CurrentThread.total.addAndGet(CurrentThread.c.get()); 
        System.out.println(this.threadName + " " + String.valueOf(CurrentThread.c.get()) + " " + CurrentThread.total.get() + " " + System.nanoTime()); 
       } 
      } 
     } 
} 

回答

4

你同步上this,這是有效的不同步可言,因爲每個線程都有一個不同的Runnable實例。

同步上的東西所有Updater實例之間共享,而不是,例如Updater.class


但是請注意,上AtomicLong同步是一個有點代碼味道的 - 它的意思做的事情已經原子。

您可以使用compareAndSet代替,避免完全同步,例如:

while (CurrentThread.c.get() < 10000) { 
    while (true) { 
    long currValue = CurrentThread.c.get(); 
    if (currValue >= 10000) break; 

    long newValue = currValue + 1; 

    // Only sets c to newValue if its value is still currValue. 
    if (CurrentThread.c.compareAndSet(currValue, newValue)) { 
     long total = CurrentThread.total.addAndGet(newValue); 
     System.out.println(
      this.threadName + " " + newValue + " " + total + " " + System.nanoTime()); 
     break; 
    } 
    } 
} 

注意,這利用了「已知」的值,比如newValuetotal,而不是從AtomicLong再次得到他們。

+0

會在哪裏正確的地方是使用了synchronized修飾符?目前正在通過實踐中的Java Concurrency一書。 –

+1

這是一個令人難以置信的廣泛問題 - 無論您需要以原子方式執行多個操作,並且相對於其他線程完全相互獨立。關鍵是你不需要它,因爲AtomicLong提供了一種替代(和更輕的)方法。 –

+0

因爲共享的'public static AtomicLong total'提供了原子操作,所以在這裏不需要任何同步。 (我沒有使用'AtomicLong',但它應該按照指定的方式行事) – sura2k