Question about Java synchronized

2019-01-14 04:06发布

The Java documentation says that "it is not possible for two invocations of synchronized methods on the same object to interleave". What I need to know is whether synchronized will also prevent a synchronized method in two different instances of the same class from interleaving.

E.g. class Worker has method called process(). We have several instances of Worker running in their own threads. We want to prevent more than one instance running the process() method simultaneously. Will synchronized do this?

Thanks.

7条回答
迷人小祖宗
2楼-- · 2019-01-14 04:16

No; synchronized only prevents multiple threads from simultaneously executing the method in the same instance. If you have n instances, there could be n threads, each executing the method in one of the instances.

If you need to ensure that only one thread may execute the method across all instances, you should make the method static, or make the method non-synchronized and rather use a synchronized block inside the method to lock on a private static field.

Edit: Note that synchronizing on a private instance variable is preferrable to having a synchronized method or to synchronize on this, and that locking on a private static instance variable is preferrable to having a static synchronized method or an instance method that synchronizes on this.getClass(). The reason is that this and this.getClass() are object references that are accessible throughout the program, so anybody may synchronize on these objects, and thereby block threads that want to call your method.

Edit: Also, see @Cowan's comment below - summary: if you really want to lock on the class, you might want to use synchronized (Worker.class) rather than synchronized (this.getClass()), depending on what effect you want in the case of subclassing.

查看更多
来,给爷笑一个
3楼-- · 2019-01-14 04:18

No, synchronized will not do this. More specifically synchronized on the instance level will not do this. Instead you will have to synchronize on the class level.

For example instead of having:

public synchronized method()
{
    //do stuff
}

You will have to code as:

public void method()
{
    synchronized(this.getClass())
    {
        //do stuff
    }
}
查看更多
何必那么认真
4楼-- · 2019-01-14 04:22

No, the method synchronized locks on the specific object (the 'this'), so 2 instances of the same class would lock on different objects.

If you want to synchronize across all instances of a class, you need to use a synchronized block IN the method, locking on a static final object.

查看更多
女痞
5楼-- · 2019-01-14 04:22

If you make the method process static, it would only allow one invocation of the method at the same time.

If that is not possible, have a static variable, say Integer lock; And use synchronized (lock) inside your method process. that is

process()
{
    synchronized (lock)
    {

        // all your code

    }
}
查看更多
做自己的国王
6楼-- · 2019-01-14 04:34

I slightly disagree with Aasmund -- though agree a bit at the same time: If you use a construct like this:

class Worker {
...
 public synchronized void process() {...}
}

then Aasmund is right -- that won't prevent multiple instances of the Worker class to execute process() in parallel. However, you can use the synchronized keyword still to synchronize on a static member to prevent that from happening:

class Worker {
 static Object o = new Object();
 ...
 public void process() {
  synchronized(o) {
   ...//perform the work here
  }
 }
查看更多
【Aperson】
7楼-- · 2019-01-14 04:35

Not unless the method is static. A synchronized non-static method takes a lock on the object (instance) on which it is invoked, not on the class.

A synchronized static method takes a lock on the class, so that could help - but it's often not very practical.

What you could do is have a static member object in your class, and do a synchronized block on that (class-global) object in your process method.

查看更多
登录 后发表回答