views:

113

answers:

4

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

+2  A: 

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.)

davetron5000
This is very, very wrong. `synchronized` on the method synchronizes on `this`, which is of no help if you have >1 instance accessing the same class field. You've just created a threading problem.
cletus
There is only 1 copy of the Foo class... his safe methods are fine. His only thread saftey bug is if the unsafe methods are used.
bwawok
@bwawok note the OP's edit, "X instances of class Test" so this answer does *not* safely access a class data member.
cletus
synchronizing on a STATIC method will synchronize on the class, not the instance. @davetron5000 has a great example that is very clear to english speakers as to what practices are safe and what practices are unsafe. @cletus, I recommend you read: http://stackoverflow.com/questions/578904/how-do-synchronized-static-methods-work-in-java
Tim Bender
+2  A: 

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();
  }
}
abhin4v
It would be better to make someNumber and otherNumber Integers, and then just lock on them. (lock objects are usually silly). Or better yet, use AtomicInteger and get better performance.
bwawok
Yes, `AtomicInteger` is surely a better solution here. I was illustrating the usage of `synchonized` with static members.
abhin4v
The illustration would be clearer with locks on the object you are using, instead of pretend lock objects....
bwawok
+1 this is the only answer that safely accesses class data members when there is more than one instance of `Foo` although `AtomicInteger` does make more sense for the *specific* example.
cletus
@bwawok locks on the objects themselves are problematic. What if those values are primitives (as in this case) or you need to cater for `null` values or you're assigning a new value? Lock objects are a better solution here.
cletus
I know how synchronization works, I want to know the effect it will have or how to use it properly with multi threading on different instances of the same object, not static objects in a class.
TacB0sS
I don't understand your answer relevance to my question?see my update...
TacB0sS
If you can't lock on the object because it is a primitive, then you should use an Atomic version of the primitive and take advantage of CAS operations.I personally find using `new Object()` as a lock a deplorable practice. In particular because j.u.c.Lock is shown to be more efficient. I realize that as of Java 1.6 the disparity between efficiency of intrinsic and explicit locks was vastly reduced. I am also aware that "Concurrency in Practice" recommends intrinsic locking because hypothetical JVM implementations on hypothetical architectures built for concurrency will be more efficient.
Tim Bender
A: 

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.

bwawok
That was not my question you know, I know how class loading works, I've implemented this before, and tested all sorts of class loading limits, but I want to know about multi threading problems with number of instances of the same class object...
TacB0sS
@TacB0sS - so why did you mention class loading in your question???
Stephen C
To strongly claim that the byte code of the Class<Foo> object loads into the memory ONLY once, unless you use ClassLoaders to load more...
TacB0sS
+3  A: 

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.

Tim Bender
thank you! that is what I needed!!
TacB0sS
But you know each class has only one instance of the method object in the class object. aren't all the calls to the method is executed via this Method object?
TacB0sS
I don't think the JVM does the reflective access you think it does. In any case, if you were to use reflection to gain access to a Method object from a Class, rest assured that what Sun's implementation gives you is a copy of the Method object it created when loading the class. Also, attempts to call invoke on that Method instance are thread-safe with synchronization in a couple places. You can always inspect Sun's source yourself via the src.zip file in any JDK download.
Tim Bender
thanks again... I've got my answer. I'll test it when I'll get to it...
TacB0sS
@TacB0sS, even if them `Method` objects were used for normal invocations, it *is* safe for multiple threads to use the same object *if they do not modify it* (and it has been published safely).
gustafc
Bottom line is? the problems only occur when more then one thread accessing a single instance of an object??
TacB0sS
Problems can occur when multiple threads access a mutable object. Even then, you have to get unlucky, which is what makes concurrency so hard to debug. Sometimes, you get lucky, and sometimes you don't. Worse yet, actively debugging can make the problem go away because you halt execution of threads... thereby reducing concurrency. So read a good book like "Effective Java" or "Java Concurrency in Practice" try to use the concepts for a few months, then read another or the same one.
Tim Bender