我有一个使用线程求和的数字数组。为了避免出现竞争情况,将增加总和变量的代码块包装在synchronized
中。最初,我将其包装在synchronized (this)
中,但效果很好。
但是,我试图理解当this
以外的内容作为锁定值传递时会发生什么。我试图将锁定锁定为synchronized (new Object())
,以便每次执行时锁定值都不同。但是它仍然可以正常工作,尽管我希望它会中断,因为现在值-锁定对象的引用每次都会更改:
public class SumNumbersCommon {
private static int totalSum;
private static int[] numbers = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
public static void main(String[] args) throws Exception {
System.out.printf("Usual sum: %,d\n", sum(numbers));
int left = numbers.length / 2;
Thread leftThread = new Thread(new SummerThread(0, left));
Thread rightThread = new Thread(new SummerThread(left + 1, numbers.length - 1));
leftThread.start();
rightThread.start();
leftThread.join();
rightThread.join();
System.out.printf("total sum: %,d\n", totalSum);
}
static class SummerThread implements Runnable {
private int min;
private int max;
public SummerThread(int min, int max) {
this.min = min;
this.max = max;
}
@Override
public void run() {
for (int i = min; i <= max; i++) {
synchronized (new Object()) {
totalSum += numbers[i];
}
}
}
}
public static int sum(int[] numbers) {
int result = 0;
for (int n: numbers) {
result += n;
}
return result;
}
}
为什么它仍然起作用?在哪种情况下,我会使用synchronized (this)
以外的其他方式?
您的线程仅执行一些琐碎的计算,因此您没有机会观察数据竞争。如果线程运行时间更长,则应观察到不一致之处。
synchronized(this)
将使用this
上的监视器,因此将对this
的任何其他同步块和所有同步方法进行序列化。在此特定示例中,synchronized(this)
将毫无意义,因为两个线程的this
将不同。您需要一个共享对象来锁定。
synchronized(obj)
可用于以更细粒度的方式控制同步。它不会影响对象的所有同步方法,而只会影响使用obj
作为锁定对象的同步块。例如,这可以用于仅修改对象状态的子集,或修改不属于对象状态的某些其他共享状态。