下面的内容可以理解为什么?
我已经经历过 发布在SO,但仍然无法组装它。

代码1:

synchronized(this){ 
// some code
}

代码2:

Object lock = new Object();

synchronized(lock){
// some code
}

任何教程,或者一些解释同步的链接,就像他们向孩子解释一样?

有帮助吗?

解决方案

在已经给出的否则优良的答案没有提到的一件事是代码1和代码2之间的差别。在代码1,同步是在该代码中发现的对象的实例,而在代码2,它的对象中的特定对象的锁上。

如果有仅在封闭类的两个同步块,就没有在两者之间的功能差,但认为这是:

class CodeOneClass {
  ...
  synchronized(this) {   // or merely "synchronized" - it defaults to this
      first protected code block
  }
  ...
  synchronized(this) {   
      second protected code block
  }
...
}

class CodeTwoClass {
  ...
  Object lock1 = new Object();
  synchronized(lock1) {   
      first protected code block
  }
  ...
  Object lock2 = new Object();
  synchronized(lock2) {   
      second protected code block
  }
...
}

如果两个线程都尝试使用CodeOneClass的相同实例,其中只有一个可为的任一二级保护码块是在同一时间的。

但随着第二成语,您可以灵活地说,它是安全的一个线程是在第一保护块,另一个是在其他。请注意,如果锁是相同的(都是相同的锁定对象上同步),则该行为将是作为第一

有其他的差异。一些作家开始以指出问题的同步(这) - 我想指出你另一篇文章在这里SO: 避免同步(本)中的Java?

我强烈建议你阅读它,并将其链接到三个职位。

其他提示

基本上,Java 中的每个对象都有一个关联的“锁”。

当线程到达对synchronized(something)的调用时,它必须在继续之前获取某物的锁。如果你想一次只允许一个线程修改一个对象的状态,最明显的事情就是同步该对象的锁。如果允许并行调用不同的方法,则需要不同的锁。

如果您编写synchronized(this),或者只是synchronized,则线程必须获取与当前对象(调用其方法)关联的锁。

请注意,从 Java 5.0 开始,并发包提供了适当的 可以使用它来代替同步。

把一个synchronized块内的代码基本上是指,“一旦这个代码开始运行时,需要使用该对象在同一时间不能运行其他代码。”

所以,如果线程#2是你的code2块执行的代码,当它涉及到它有效地环顾四周,在所有其他线程,以确保没有其他人的synchronized(lock)代码运行“同步”的代码与lock对象在这一刻。线程#1肯定是运行的一些是在同一时间码,但也可能是完全无关的代码。如果是这样,它是线程#2安全开始投放“some code”的东西。

同时,如果线程#1获取到synchronized(this)块,它也有暂停和查看是否有任何其它线程使用this。如果this是相同的对象lock,我们有一个问题。我们被告知,只有一个线程都不可能使用该对象(在synchronized块)在同一时间。然而,线程#2已经在使用它。主题1号就只能等待...等待...等待......直到最终线#2结束。然后,我们可以继续进行。

最终的结果是,只有一个synchronized块可以一次运行(与特定对象,当然)。

假设有一个 Account 对象,其中有一个方法:

void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
   if (accountBalance >= debitAmount) {
      accountBalance -= debitAmount;
      beneficiary.credit(debitAmount);
   }
   else {
      throw new InsufficientFundsException();
   }
}

现在假设你有一个帐户的结余为100欧元,你会得到两次试图借记它70欧元。如果两个借记同时发生的,你可以得到一个 比赛的状况 是这样的:

  • 首先借记检查的账户余额:100>=70,这样成功
  • 第二借记检查的账户余额:100>=70,这样成功
  • 第一次账执行;帐户余额变为30
  • 第二借记执行;帐户余额的变-40. 不应该允许

我们可以防止这种可怕的事态的通过同步上 Account 对象锁定:

void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
   synchronized (this) {
      if (accountBalance >= debitAmount) {
         accountBalance -= debitAmount;
         beneficiary.credit(debitAmount);
      }
      else {
         throw new InsufficientFundsException();
      }
   }
}

这可以确保测试的账户余额和借方不能中断另一个测试的账户余额。

太阳Java教程 是一个很好的地方开始的信息,并发和锁。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top