【问题标题】:Java / Android: LinkedList race conditionJava / Android:LinkedList 竞争条件
【发布时间】:2012-10-28 18:07:48
【问题描述】:

我在一个 android 应用程序中使用LinkedList,在那里我遇到了竞争条件。 1 个线程将数据添加到LinkedList,而另一个线程在检索到它们时将其删除。我遇到了从未处理过我新添加的对象的情况。

我在 Google 上搜索了 Java 同步对象,但要么我想得太简单,要么我遗漏了一些东西。从我读过的内容来看,“对象同步”是两者中比较难的,所以我想知道用sychronized(object) { }; 封装一段代码是否足够?

所以,我有:

public void function addMove(Object move) {
  synchronized(list) {
    list.add(move);
  };
};

public void function second() {
   synchronized(list) {
   // iterate through the list
   list.clear;
  };
};

这真的是我所需要的吗?

【问题讨论】:

  • 参见 java.util.Collections.synchronizedList。
  • 为什么不只是 public void synchronized function() ?
  • 您是否遇到语法错误?我不熟悉方法声明中的 function 词。你可能只需要public void addMove(Object move) {...}public void second() {...}
  • 为什么使用clear 而不是remove(可能是删除)?
  • 因为由于竞争条件,我在 remove() 方面遇到了问题。如果在我的迭代循环期间更改了 LinkedList,则 remove() 需要更改的“位置”。所以这会导致错误的项目被删除。只需 clear()'ing 整个列表就可以正常工作了,因为它已经同步了。

标签: java android linked-list synchronized


【解决方案1】:

- 在您的情况下,如果您的列表与对象正确耦合并且除了这种唯一方法之外没有其他方法可以访问它,那么我认为这就足够了。

- 此外,还可以使用以下方法:

public class Test{

 private LinkedList<Object> list = new LinkedList<Object>();

 public void function addMove(Object move) {
  synchronized(this) {
    list.add(move);
  }
}

public void function second() {
   synchronized(this) {
   list.clear;
  }
 }


}

/////////////////////////////编辑部分//////// //////////////

- Synchronization 用于保护数据的关键状态,并应用methodatomic statements访问要保护其数据的field

- Every object一个且只有一个锁,这是由thread 获得以访问synchronized 方法 strong> 或 atomic statements 可以访问其instance variables

-同样every Class一个且只有一个锁,这是由一个线程来获取synchronized方法 > 或 atomic statements 可以访问其static variable

- 现在,当thread 获得对对象锁的访问权限后,它便获得对其同步方法或原子语句的访问权限,并且 如果此时另一个线程尝试访问同一个对象锁,然后该线程被拒绝访问并移动到blocked state

【讨论】:

  • 谢谢。使用这种方法代替我的方法有什么好处?它到底是做什么的?它同步整个班级?这是否意味着如果 2 个线程正在访问此类中的一个变量,其中一个必须等​​待? (不管他们是否访问同一个变量)
  • 不错的答案! @user1750795,这确保没有 NullPointerExceptionsychronized 对象,同时提供阻塞解决方案。
  • @JBNizet 因为这个同步块基于当前对象,它不会阻塞所有实例...每个实例都有自己的实例变量副本。我希望这是基本的 java跨度>
  • 当您的代码使用 Test.class 作为锁而不是像现在这样使用 this 时,我发表了评论。
  • @JBNizet 请不要否定答案,直到你确定你在说什么......我已经在给出答案的 5 到 6 秒内改变了 Test.class ......我有不知道它没有更新....
【解决方案2】:

如果列表被正确封装到您的对象中(即没有其他对象可以访问该列表),并且如果这些是访问列表的唯一方法,那么是的,这就是您所需要的。

关键是对列表的每次访问都必须在同步块中完成。并且每个同步块必须在同一个对象上同步(list,在您的代码示例中)。

【讨论】:

    【解决方案3】:

    是的,这就是您控制对象线程访问的方式。您所要做的就是查看您的方法的时机。只有在列表中添加了数据时才应调用 clear 命令。

    【讨论】:

    • 这是为什么呢?为什么我不能在我想要的时候调用 clear() ?如果它已经是空的,什么都不会发生,对吧?
    【解决方案4】:

    我不知道Android是否支持Java 5,但是java.util.concurrent包含很多优秀的类来支持队列,例如ConcurrentLinkedQueue。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      • 1970-01-01
      • 2022-01-23
      • 2018-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多