获得正确的同步
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
我想它一定就在我的正前方,但是我找不到。
你保证两个线程同步执行,但不保证执行顺序。
所以 incrementValues 和 addValue 将处于竞争状态。您有重复的变量,因为 addValue 有时会在 incrementValues 之前执行。
如果你想保证没有任何重复的顺序,你应该实现一个门来确保 incrementValues 和 addValue 被正确执行订单。
顺便说一句:我认为 Main class 中的同步块是不必要的,因为您已经锁定了值 class.
我做了一点测试,因为我想存储一个数组(或某种列表),一次将被多个线程使用。
我的主-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
我想它一定就在我的正前方,但是我找不到。
你保证两个线程同步执行,但不保证执行顺序。
所以 incrementValues 和 addValue 将处于竞争状态。您有重复的变量,因为 addValue 有时会在 incrementValues 之前执行。
如果你想保证没有任何重复的顺序,你应该实现一个门来确保 incrementValues 和 addValue 被正确执行订单。
顺便说一句:我认为 Main class 中的同步块是不必要的,因为您已经锁定了值 class.