阻止与2个对象同步不起作用

时间:2012-09-28 20:16:52

标签: java synchronized

我正在测试一个代码,其中我有两个方法,并且每个方法中的一个语句是同步的。

private final Object obj1 = new Object();
private final Object obj2 = new Object();

public void method1(int result)
{
 //there's a loop to create delay

 synchronized (obj1){
   sum = sum + result;
 }

 //there's a loop to create delay

}


public void method2(int result)
{
  //there's a loop to create delay

 synchronized (obj2){
   sum = sum - result;
 }

 //there's a loop to create delay

}

我基本上做的是将结果添加到sum然后减去相同的数量然后打印总和。所以我的初始和最终金额应该是不变的。

问题是当我使用2个差异对象作为锁时,我不知道为什么最终数量与初始数量不同。然而,当我使用'this'对象作为两个语句的锁时,它是不变的。但是使用'this'作为对象并没有比使用同步方法更快地执行。

我还是同步概念的新手,所以感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

当您在synchronize块中指定对象时,该对象的使用方式类似于该块的锁定:任何时候只有一个synchronize块可以使用锁定对象。

当您使用两个不同的对象作为锁时,它们会变成两个不同的锁:两个线程可以同时锁定它们 - 每个锁一个线程。这解释了不一致的结果:两个线程可以同时获取两个单独的锁,并同时修改sum,导致计算错误。

您应该使用单个锁来保护单个资源免受并发访问。当您使用this时会发生这种情况;如果您在obj1块中使用obj2synchronize,则会发生同样的情况,除非在这种情况下,您的对象的用户无法通过同步来导致您的方法永久阻止你的对象,故意不释放锁。

答案 1 :(得分:0)

如果您希望在synchronized上同步操作,则obj1块应位于同一对象上(obj2(或)sum)。

否则每个线程获取一个对象的锁定,并且它们可以同时执行操作。

每个线程在执行任何受保护的代码之前获取对象的锁定。 T1可能获得Obj1的锁定,而T2可能会获得Obj2同时锁定并继续执行,这可能会产生不一致的结果。