14

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.

TacB0sS
  • 10,106
  • 12
  • 75
  • 118
  • You need to supply some more information. Are the X instances of the same class? Is an atomic operation over multiple instances at the same time? What exactly is the situation? – cletus Jun 23 '10 at 03:50
  • but of course, what would be the whole point for that question other wise? – TacB0sS Jun 23 '10 at 03:58
  • If each thread has its own instance of the class `Test` and you have the guarantee that one thread will never access other thread's instance, then the access to the instance level members need not be synchronized. You still have to synchronize the access to class level members (as I put in my answer) because there is only one class at anytime and it is shared among all the threads. – Abhinav Sarkar Jun 23 '10 at 04:33
  • Looking back three years... so much that I have learned about multi threading, makes this question kind of amusing to look at... but still I believe this is a non-trivial question for these with less experience as I once was! – TacB0sS Aug 31 '13 at 21:25

5 Answers5

14

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
  • 20,112
  • 2
  • 49
  • 58
  • 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 Jun 23 '10 at 06:01
  • 1
    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 Jun 23 '10 at 07:47
  • @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 Jun 23 '10 at 08:39
  • Bottom line is? the problems only occur when more then one thread accessing a single instance of an object?? – TacB0sS Jun 23 '10 at 09:13
  • 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 Jun 23 '10 at 09:53
3

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
  • 24,123
  • 11
  • 70
  • 98
  • 2
    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 Jun 23 '10 at 03:49
  • 1
    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 Jun 23 '10 at 03:58
  • 2
    @bwawok note the OP's edit, "X instances of class Test" so this answer does *not* safely access a class data member. – cletus Jun 23 '10 at 04:04
  • 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 Jun 23 '10 at 05:02
2

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();
  }
}
Community
  • 1
  • 1
Abhinav Sarkar
  • 23,534
  • 11
  • 81
  • 97
  • 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 Jun 23 '10 at 03:59
  • Yes, `AtomicInteger` is surely a better solution here. I was illustrating the usage of `synchonized` with static members. – Abhinav Sarkar Jun 23 '10 at 04:03
  • The illustration would be clearer with locks on the object you are using, instead of pretend lock objects.... – bwawok Jun 23 '10 at 04:04
  • 2
    +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 Jun 23 '10 at 04:06
  • @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 Jun 23 '10 at 04:07
  • 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 Jun 23 '10 at 04:07
  • 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 Jun 23 '10 at 05:08
0

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.

nihar
  • 135
  • 1
  • 17
0

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
  • 14,898
  • 7
  • 32
  • 43
  • 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 Jun 23 '10 at 04:06
  • To strongly claim that the byte code of the Class object loads into the memory ONLY once, unless you use ClassLoaders to load more... – TacB0sS Jun 23 '10 at 04:49