开发者

My Long pending confusion on multi-threading in Java. Need help

开发者 https://www.devze.com 2022-12-20 16:01 出处:网络
I am having this doubt about multi-threading and I have faced lots of questions about in multi-threading in many of the interviews.

I am having this doubt about multi-threading and I have faced lots of questions about in multi-threading in many of the interviews.

I speak a lot of about acquiring a loc开发者_如何学编程k on the object as such. My doubt is when you have two methods that are synchronized and there are two threads which wants to access those two methods, ThreadA wants to access MethodA and ThreadB wants to access MethodB.

Now both the methods are in the same object. But I use to say acquiring lock on an object and i have not heard acquiring lock on a method. Now Can both the threads parallely access MethodA and MethodB? My assumption is once you acquire lock on object, no other thread on work on it. Isnt it?

And what is the significance synchronized(XYZ.class)?


No, they cannot. If I understand you correctly then you mean:

class Foo {

   public synchronized void methodA () {
      doSmth ();
   }

   public synchronized void methodB () {
      doSmthElse ();
   }

}

In this case synchronized modifier is equal to:

class Foo {

   public void methodA () {
      synchronized (this) {
         doSmth ();
      }
   }

   public void methodB () {
      synchronized (this) {
         doSmthElse ();
      }
   }

}

This means that only 1 thread can work at the same time inside one of these 2 methods on each Foo-object.

And what is the significance synchronized(XYZ.class)?

That's what you have behind the scenes of

class XYZ {
   public static synchronized void someMethod () { ... }
}


Declaring a method as synchronized is basically the same as containing the entire method body in a "synchronized(this) { ... }" block. So the lock on synchronized method is on the entire object instance, meaning that you are locking out others who want to use synchronized methods on that same object. If you want per method synchronization instead of per object synchronization you will have to synchronize on something else, either by using synchronized(guardObject) in that particular method or by using one of the Lock objects in java (most of them added in 1.5).

And what is the significance synchronized(XYZ.class)?

This means that you are using the class as a guard object, it means that the lock in the class itself (not the instance) will be protecting access to the block. The difference to using the object instance as a guard is that if you have ten thousand objects you will only be able to access one of them at a time, compared to protecting access by more than one thread to an instance at a time.


If methodA and methodB use different data structures, and it's safe to call methodA while somebody else is calling methodB, then those two methods should use different locks.

Here's the skinny on synchronized(XYZ.class)

synchronized (XYZ.class) is how you implment the above pattern -- it's a synchronized block that:

  • acquires a lock on an object (in this class the instance of java.lang.class that represents XYZ)
  • does some work
  • releases the lock.

The key is to remember that every object in Java has a lock (the technical term is a monitor) that can be held by only one thread at a time. You can request the lock for any object that you have a reference to.

The synchronized keyword on a method:

public synchronized void foo() {
    //do something
}

is just syntactic sugar for this:

public void foo() {
    synchronized(this) {
        //do something
    }
}

There is one significant drawback to this approach: since anyone with a reference to an object can acquire its lock, synchronized methods won't work properly if an external caller acquires and holds the object lock.

(Incidentally, this is why locking on XYZ.class is also a bad idea: it's a globally accesible object, and you never know who might decide to acquire its lock)

To avoid these drawbacks, this pattern is usually used instead of the synchronized method:

private final Object LOCK = new Object();
public void foo() {
    synchronized(LOCK) {
        //do something
    }
}

Since no external caller can have a reference to the LOCK object, only this class can acquire its lock, and the synchronized method will always work as expected.

When you have two different methods that need to be locked separately, the usual way to do that is for each method to lock on a different privately held object:

private final Object LOCKA = new Object();
private final Object LOCKB = new Object();
public void foo() {
    synchronized(LOCKA) {
        //do something
    }
}

public void bar() {
    synchronized(LOCKB) {
        //do something else
    }
}

Then it's possible for a thread to call foo() while another thread is calling bar(), but only one thread will be able to call foo() at a time, and only one thread will be able to call bar() at a time.


Using synchronized(XYZ.class) is very restrictive. This means whatever code is being guarded by this XYZ.class will be executed by one thread only at the same time. You should be aware of this as it could lead to severe starvation problem.


A thread entering into monitor on entrance to critical section defined as 'synchronized' So you can define each method (not the whole class) as synchronized or even a code block within a method. http://java.sun.com/docs/books/tutorial/essential/concurrency/locksync.html

0

精彩评论

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

关注公众号