获得正确的同步

get the synchronisation right

我做了一点测试,因为我想存储一个数组(或某种列表),一次将被多个线程使用。

我的主-Class:

package main;

import java.util.Timer;
import java.util.TimerTask;

public class Main {
private final static Object lock = new Object();

public static void main(String[] args) {
    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {

        @Override
        public void run() {
            synchronized (lock) {
                Values.incrementValues();
            }
        }

    }, 1000, 1000);

    Timer timer1 = new Timer();
    timer1.scheduleAtFixedRate(new TimerTask() {

        @Override
        public void run() {
            synchronized (lock) {
                Values.addValue(0);
            }
        }

    }, 1000, 1000);

    Timer timer2 = new Timer();
    timer2.scheduleAtFixedRate(new TimerTask() {

        @Override
        public void run() {
            synchronized (lock) {
                Values.printValues();
            }
        }

    }, 1000, 1000);
}
}

这是 Class 我将数组存储在: 主包;

public class Values {
static int[] values = new int[1];
private final static Object lock = new Object();

public static void incrementValues() {
    synchronized (lock) {
        for (int i = 0; i < values.length; i++) {
            values[i]++;
        }
    }
}

public static void addValue(int e) {
    synchronized (lock) {
        int[] temp = values;
        values = new int[temp.length + 1];
        for (int i = 0; i < temp.length; i++) {
            values[i] = temp[i];
        }
        values[temp.length] = e;
    }
}

public static void printValues() {
    printValues(values);
}

public static void printValues(int[] values) {
    synchronized (lock) {
    }
    StringBuilder sb = new StringBuilder();
    for (int e : values) {
        sb.append(e);
        sb.append(' ');
    }
    System.out.println(sb.toString());
}
}

我应该得到的输出是一行数字,如:10 9 8 7 6 5 4 3 2 1 0

但我得到的是 21 21 19 18 17 16 15 15 14 13 11 10 9 8 7 6 6 5 4 2 1 0

我想它一定就在我的正前方,但是我找不到。

你保证两个线程同步执行,但不保证执行顺序。

所以 incrementValuesaddValue 将处于竞争状态。您有重复的变量,因为 addValue 有时会在 incrementValues 之前执行。

如果你想保证没有任何重复的顺序,你应该实现一个门来确保 incrementValuesaddValue 被正确执行订单。

顺便说一句:我认为 Main class 中的同步块是不必要的,因为您已经锁定了值 class.