java中的同步不正确

时间:2017-05-04 16:52:44

标签: java multithreading synchronization synchronized

所以,我正在尝试了解java线程和同步。以下代码没有正确同步,有人可以解释原因吗?

Digest: sha256:ca50223ff969665a64ed3b690124f56d1cc51754331e94baa80327dcc474c020
Status: Image is up to date for appsvc/apps:wordpress
wordpress: Pulling from appsvc/apps
Digest: sha256:ca50223ff969665a64ed3b690124f56d1cc51754331e94baa80327dcc474c020
Status: Image is up to date for appsvc/apps:wordpress
wordpress: Pulling from appsvc/apps
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( );
     }
     }
}

我的预期输出是2000.我的实际输出介于0到2000之间。

2 个答案:

答案 0 :(得分: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( );
     }
     }
}

此外,synchronizedwait/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();
       }
     }
}

答案 1 :(得分:0)

如果您不想使synchronized方法静态(例如,因为您正在访问实例变量),则可以将锁保存在静态内部对象中。 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();
        }
    }
}