题
下面的内容可以理解为什么?
我已经经历过 这 发布在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教程 是一个很好的地方开始的信息,并发和锁。