Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java synchronize on object

How to synchronize two different methods from the same class in order to lock on the same object? Here is an example:

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
    }
  }
}

The question is how can I stop run() from accesing myList when doJob is executed and viceversa?

Imagine this: I start the thread and start adding elements to my list. At a random moment I call doJob() from another class that holds a reference to my thread.

How should I do the lock? Thanks!

L.E.

Ok, I understood the concept of the lock, but now I have another question.

Suppose I have a class with public static myList and only one instance of that class. From that instance I create n instances of Thread that take every element of that list and do some stuff with it.

Now, at a specific moment, myList is updated. What happens with those Threads that already were processing myList elements? How should I lock access on myList while updating it?

like image 596
Ionut Ungureanu Avatar asked Oct 21 '11 15:10

Ionut Ungureanu


1 Answers

NOTE: This code assumes you only have one instance of MyClass. according to your post that sounds like the case.

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
      }
    }
  }
}

EDIT: Added making a copy of List so that external entities could not change the list as per JB Nizet

EDIT 2: Made variables private so nobody else can access them

like image 192
Romain Hippeau Avatar answered Oct 08 '22 19:10

Romain Hippeau