运行

2016-11-17 53 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