在Java中同步块之后的代码

4

我是一个有用的助手,可以为您翻译文本。

以下是需要翻译的内容:

我有一个简单的问题,但是无法找到正确的答案。假设我们有:

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }

    nameList.add(name);
} 

在同步块后面的代码怎么处理呢?我的意思是,同步块用于减少锁的范围,但这里同步块后面的代码(namelist.add(name))会被阻塞,对吧?
假设线程A调用了上述函数,但它将等待“this”锁被线程B释放,因为线程B之前在某个其他方法上拥有该锁。现在,我想知道当线程A在等待“this”锁对象时,执行是否会从B的nameList.add(name)方法恢复——因为nameList.add(name)不在同步块中。

问题不够清晰,您所说的“block”是指什么?除了同步块以外的任何代码都不会被同步 - 如果这是您的意思。 - Nir Alfasi
请明确“blocked”一词的具体含义,因为我们不知道这具体指的是什么(这不是一个标准的Java术语,而且我猜它对你个人来说有特殊意义...)。 - Emily Mabrey
好的。让我再试一次。假设线程A调用了上面的这个函数,但它将等待'this'锁被线程B释放,因为线程B之前在某个其他方法上拥有了该锁。现在,我想知道当线程A在等待'this'锁对象时,执行是否会从B的nameList.add(name)方法恢复——因为nameList.add(name)不在同步块中。 - stdout
3个回答

7
现在,我想知道当线程A等待“this”锁对象时,执行是否会从B的nameList.add(name)方法恢复 - 因为nameList.add(name)不在同步块中。

不,执行该方法的线程不能跳过同步块并执行方法的其余部分。它将阻塞直到可以获取this上的监视器,然后执行同步块,然后释放this上的监视器,然后将字符串添加到nameList中。

如果并发线程执行此操作,则无法保证哪些线程将首先插入nameList。在线程释放this上的监视器并添加到nameList之间,可能会有一个或多个其他线程插入到列表中。

另外,无论nameList实现为何,都需要是线程安全的集合,以便并发更改不会导致错误,并且更改在线程之间可见。例如,如果nameList是ArrayList或HashSet,则这将不安全。


0

原则上,关键字synchronized有以下两个作用:

  • synchronized关键字保护的代码不能被多个线程同时执行;

  • 它控制线程之间数据(变量)的可见性;

    在您的示例中,不在synchronized范围内的代码将可以被调用此方法的所有其他线程访问;

假设超出范围的操作是写入操作,则通常希望将其synchronized以减少可能出现的任何异常。


0

synchronized(this) 在另一个线程进入此块时会阻塞,直到它离开此块。如果该线程离开此块,则等待的线程中有一个机会(在其他等待线程中)进入该块。namelist.add() 在同步范围外执行,因此可能与其他线程并行执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接