2017-05-04 64 views
1

所以,我想了解java線程和同步。下面的一段代碼沒有得到正確的同步,有人可以解釋爲什麼嗎?在java中不正確的同步

package threadPractice; 

public class T2 extends Thread { 
    public static int count=0; 
    public T2() { } 
    private synchronized void update() { 
     int v = count; 
     try { 
      sleep(10); 
     } catch (Exception e) { } 
     v++; 
     count = v; 
    } 
    public void run() { 
    for (int i = 0; i < 1000; i++) { 
    update(); 
    } 
    } 
} 
package threadPractice; 

public class Main { 
    public static void main(String args[]) throws Exception { 
     T2 t1_1 = new T2(); 
     T2 t1_2 = new T2(); 
     t1_1.start(); t1_2.start(); 
     t1_1.join(); t1_2.join(); 
     System.out.println("T2.start, "+T2.count); 

    } 
} 

我的預期成果是2000年我的實際產量好0年至2000年和

+0

你是什麼意思**以下代碼段不能正確同步**? –

+0

你可以把你的實際和預期的產出。 – hagrawal

回答

3

因爲你讓兩個不同的對象進行同步的。如果您想鎖定一個字段(count),則需要使用一個鎖。爲每個線程分配自己的鎖意味着任何線程都不知道其他線程何時實際使用該鎖。

如果您的字段是公開的,則首先不受保護。使其私密。

其次在這種情況下使用靜態方法來保護靜態字段。

public class T2 extends Thread { 
    private static int count=0; 

    private static synchronized void update() { 
     int v = count; 
     try { 
      sleep(10); 
     } catch (Exception e) { } 
     v++; 
     count = v; 
    } 

    @Override 
    public void run() { 
     for (int i = 0; i < 1000; i++) { 
     update(); 
    } 
    } 
} 

此外,​​和wait/notify是低層次的原語有很多尖角的(如你發現)。更好的選擇是使用API​​。

public class T2 extends Thread { 
    private static final AtomicInteger count = new AtomicInteger(); 

    @Override 
    public void run() { 
     for (int i = 0; i < 1000; i++) { 
     count.incrementAndGet(); 
     } 
    } 
} 
0

如果您不想讓同步方法爲靜態(例如因爲您正在訪問實例變量),您可以將鎖保持在靜態內部對象中。 T2的所有不同實例都將使用相同的鎖定參考,如下所示:

public class T2 extends Thread { 
    public static int count = 0; 
    private final static Object LOCK = new Object(); // Static lock 

    public T2() { 
    } 

    private void update() { 
     synchronized (LOCK) { // Every instance of T2 uses the same lock 
      int v = count; 
      try { 
       sleep(10); 
      } catch (Exception e) { 
      } 
      v++; 
      count = v; 
     } 
    } 

    public void run() { 
     for (int i = 0; i < 1000; i++) { 
      update(); 
     } 
    } 
}