2017-05-04 41 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(); 
     } 
    } 
}