开发者

Multi-Threading on different instances of same object in Java

I've learned that every class byte code is been loaded to the memory once for each class loader, thus when a thread is executing the byte code of some method, and another thread comes along?

1 thread -> 1 instance - of class Foo == no problem.

X threads -> 1 instance - of class Foo == need to be handled this is clear.

X threads -> X respective instances - of class Foo == ????

should I make sure nothing is messed up in the method? if the method uses a instance level variables, can I be sure it will use the right ones?

Update:

I see my question was not clear to some, here is an example with numbers

I have an object of class type Foo which has no synchronization!!

I have 5 instances of that Foo with 5 threads running for/in each of them, and accessing instance level parameters for example:

class FOO {
     private SomeObject someObject=new SomeObject();

     private void problematicMethod(Data data) {
         someObject.doSomethingWithTheData(data);
         data.doSomethingWithSomeObject(someObject); 
// any开发者_如何学Python way you want it use the data or export the data
     }
}

I'm asking is there a problem here, since there is only 1 byte code of this class and 5 instances of this object that access this byte code, so if I want to prevent them from overlapping on the same byte code, what should I do?

Thanks, Adam.


I've learned that every class byte code is been loaded to the memory once for each class loader, thus when a thread is executing the byte code of some method, and another thread comes along?

Class loading and byte code is irrelevant here. Byte code is a set of assembly-like instructions which the JVM interprets and compiles into native machine code. More than one thread can safely follow the instruction sets encoded into the byte code.

1 thread -> 1 instance - of class Test, no problem

Mostly correct. If there is only a single Thread, then there is not any immediate need to make anything thread safe. However, ignoring thread safety would limit growth and re-usability.

X threads -> 1 instance - of class Test, need to be handled this is clear.

Well, yes, for thread visibility reasons and to ensure that critical regions are executed atomically, using synchronization or locking techniques is fairly important. Of course, it all depends right?! If your class doesn't have state (instance or class variables), then you don't really need to make it thread-safe (think utility class like Java's Executors, Arrays, Collections classes).

X threads -> X respective instances - of class Test, ????

If each thread has its own instance of class Test, and no single instance is shared amongst more than one thread, then this is the same as your first example. If an instance of Test is referenced by two or more threads, then this is the same as your second example.

if the method uses a class level variables, can I be sure it will use the right ones?

Class variables ARE static variables in Java. There are already two answers posted which emphasize the importance of using synchronized to prevent more than one thread from modifying a class variable at the same time. Not mentioned is the importance of using synchronized or volatile to make sure you don't see a stale version of the class variable.


You need to synchronize on the shared resource. If that resource is a class-level field, you should synchronize on the class itself:

public class Foo {
  private static int someNumber = 0;
  // not thread safe
  public void inc_unsafe()  { 
    someNumber++;
  }

  // not thread safe either; we are sync'ing here on an INSTANCE of
  // the Foo class
  public synchronized void inc_also_unsafe()  { 
    someNumber++;
  }

  // here we are safe, because for static methods, synchronized will use the class
  // itself
  public static synchronized void inc_safe()  { 
    someNumber++;
  }

  // also safe, since we use the class itself
  public static synchronized void inc_also_safe()  { 
    synchronized (Foo.class) {
      someNumber++;
    }
  }
}

Note that {{java.util.concurrent}} provides many more ways to protected shared data than Java's {{synchronized}} keyword. Look into it, as it might be what you want.

(For anyone that wants to claim that int incrementing is already thread-safe, please note this is just an example and the basic concept can be applied to anything.)


Adding to dave's answer, if you have multiple static methods that work on different static members, it is better to synchronize on separate static objects.

public class Foo {
  private static int someNumber = 0;
  private static int otherNumber = 0;
  private static final Object lock1 = new Object();
  private static final Object lock2 = new Object();

  public static void incSomeNumber() {
    synchronized (lock1) {
      someNumber++;
    }
  }

  public static void incOtherNumber() {
    synchronized (lock2) {
      otherNumber++;
    }
  }
}

In this way, two different threads can call incSomeNumber and incOtherNumber at the same time without getting stuck on synchronization.


EDIT

Here is the same example with AtomicInterger. Note that no explicit locking is required. All operations on AtomicIntergers are atomic and implemented using hardware operations. So they result in better performance.

import java.util.concurrent.atomic.AtomicInteger;

public class Foo {
  private static AtomicInteger someNumber = new AtomicInteger(0);
  private static AtomicInteger otherNumber = new AtomicInteger(0);

  public static int incSomeNumber() {
    return someNumber.incrementAndGet();
  }

  public static int incOtherNumber() {
    return otherNumber.incrementAndGet();
  }
}


All threads should go to the same class loader. 10 threads using FOo.class, all 10 will have the same exact object. The only way you would get the same class in different classloaders would be if

a) You wrote your own code that did class loader magic
b) You did something weird like include your code both inside a war, and inside of a shared tomcat lib folder... and did the right sequence of events to cause 2 copies to be loaded from different places.

In all normal cases.. you make a class, there is exactly 1 copy of the class object, and all synchronization on (this) will be across your entire application.


And I think, instance variable as local variable is unique to each thread. So by default it is thread safe.But yes, it is still needed to be taken care by synchronization.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜