Java在对象上同步

Ion*_*anu 4 java methods locking synchronize

我有一个很大的问题要问你.如何从同一个类同步两个不同的方法以锁定同一个对象?这是一个例子:

public class MyClass extends Thread implements Observer{
  public List<AnotherClass> myList = null;

  public MyClass(List<AnotherClass> myList){
    this.myList = myList;
  }

  public void run(){
    while(true){
       //Do some stuff 
       myList.add(NotImportantElement);
    }
  }

  public void doJob{
    for(int i=0; i<myList.size; i++){
      ElementClass x = myList.get(i);
      //Do some more stuff
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是如何在执行doJob时停止run()访问myList,反之亦然?

想象一下:我启动线程并开始向列表中添加元素.在一个随机的时刻,我从另一个持有对我的线程的引用的类调用doJob().

我应该怎么做锁?谢谢!

LE

好吧,我理解锁的概念,但现在我有另一个问题.

假设我有一个类,public static myList并且只有该类的一个实例.从那个实例开始,我创建了一个n实例Thread来获取该列表的每个元素并用它做一些事情.

现在,在特定时刻,myList更新.那些已经在处理myList元素的线程会发生什么?myList在更新时如何锁定访问权限?

Rom*_*eau 5

注意:此代码假定您只有一个MyClass实例.根据你的帖子,听起来像是这样的.

public class MyClass extends Thread implements Observer{
  private List<AnotherClass> myList = null;
  private Object lock = new Object();

  public MyClass(List<AnotherClass> myList){
    this.myList = new ArrayList(myList);
  }

  public void run(){
    while(true){
       //Do some stuff 
       synchronized(lock) {
        myList.add(NotImportantElement);
       }
    }
  }

  public void doJob{
    synchronized(lock) {
      for(int i=0; i<myList.size; i++){
        ElementClass x = myList.get(i);
        //Do some more stuff
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑:添加了制作List的副本,以便外部实体无法根据JB Nizet更改列表

编辑2:将变量设为私有,以便其他人无法访问它们

  • 但是有一个缺陷:因为myList来自外部,所以不能保证另一个线程直接访问myList,绕过锁.构造函数应该对它收到的列表进行防御性复制. (3认同)

Vic*_*kin 5

你可以:

  1. 声明两者run和doJob synchronized。这将this用作锁;
  2. 将列表声明为final并在其上同步。这将使用列表作为锁。将锁定字段声明为final一种很好的做法。这样,您的类的某些方法可以在一个对象上同步,而其他方法可以使用其他对象进行同步。这减少了锁争用,但增加了代码复杂性;
  3. 引入显式java.util.concurrent.locks.Lock变量并使用它的方法进行同步。这将提高代码的灵活性,但也会增加代码的复杂性;
  4. 不要完全进行显式同步,而是使用 JDK 中的一些线程安全数据结构。例如,BlockingQueue或CopyOnWriteArrayList。这将降低代码复杂度并确保线程安全。
  5. 通过读取/写入volatile字段来使用同步。请参阅此SO 帖子。这将确保安全,但会大大增加复杂性。第二个想法,不要这样做:)

  • 赞成(4.):通过使用并发列表,您将避免很多麻烦。 (2认同)