Java线程"同步"

Kev*_*ith 5 java synchronized thread-safety

文章谈到Java的"同步"的关键字.

  ...
  private int foo;
  public synchronized int getFoo() { return foo; } 
  public synchronized void setFoo(int f) { foo = f; }
Run Code Online (Sandbox Code Playgroud)

如果调用者想要增加foo属性,则执行此操作的以下代码不是线程安全的:

  ...
  setFoo(getFoo() + 1);
Run Code Online (Sandbox Code Playgroud)

如果两个线程同时尝试递增foo,结果可能是foo的值增加了一个或两个,具体取决于时间.

现在,我的问题:

为什么setFoo()上没有"同步"会阻止上面的粗体线?

rad*_*dai 6

因为您选择保证没有其他人越来越富与你们一起,并没有其他人设置foo的背部除了你,但你不是保证没有人管理你之间进入和退出(或只是)调用get()和你打电话组()

您可以将该代码视为与此完全等效:

int temp = getFoo(); //safe method
temp = temp+1; //not protected here - im not holding any locks ...
setFoo(temp); //safe method
Run Code Online (Sandbox Code Playgroud)


Sam*_*uel 6

这是一个检查 - 然后 - 行动竞争条件的例子.

可能会发生如下情况:

Thread-1 getFoo() returns 0
Thread-2 getFoo() returns 0
Thread-2 setFoo(1)
Thread-1 setFoo(1)
Run Code Online (Sandbox Code Playgroud)

这意味着两个线程已尝试递增foo,但它具有仅递增一次的效果.

正如其他答案所确定的那样,将增量与同步块锁定在getFoo()和setFoo()相同的对象上将阻止此竞争条件,因为线程将无法像上面那样交错.