How to Synchronize a Static Variable Among Threads Running Different Instances of a Class in Java

How to synchronize a static variable among threads running different instances of a class in Java?

There are several ways to synchronize access to a static variable.

  1. Use a synchronized static method. This synchronizes on the class object.

    public class Test {
    private static int count = 0;

    public static synchronized void incrementCount() {
    count++;
    }
    }
  2. Explicitly synchronize on the class object.

    public class Test {
    private static int count = 0;

    public void incrementCount() {
    synchronized (Test.class) {
    count++;
    }
    }
    }
  3. Synchronize on some other static object.

    public class Test {
    private static int count = 0;
    private static final Object countLock = new Object();

    public void incrementCount() {
    synchronized (countLock) {
    count++;
    }
    }
    }

Method 3 is the best in many cases because the lock object is not exposed outside of your class.

Synchronization between two threads using same and different instance of class?

Case2 No, the lock is for method's object. Each instance keeps a separate lock

Case3 Yes, the static method has association with a class not a object, so the lock is for the Class object. They block each other

Case4: Yes, since it's the class object, same result in invoking it on different instances

How to avoid accessing the same static counter while multithreading

You can use synchronized static method (in the increment anyway you are just operating on the static field so why not to make it static?).

public static synchronized void increment() {
x=x+1;
System.out.println(x+" "+ name);
}

Such method is synchronizing on the whole class object.

If you really don't want for some reason to make this method static you can explicitely synchronize the critical section on the class object

public void increment() {
synchronized(Test1.class) {
x=x+1;
System.out.println(x+" "+ name);
}
}

Init static variable in synchronized block for all the threads, read without synchronized

It is only safe to do this if you are guaranteed to have called init() before calling insert(data).

There is a happens-before edge created by the synchronized block: the end of the synchronized block happens before the next invocation of the same block.

This means that if a thread has invoked init(), then either:

  • client was previously uninitialized, so it is initialized on this call.
  • client was previously initialized, and the write to client is has happened before the current thread enters the synchronized block.

No further synchronization is then necessary, at least with respect to client.

However, if a thread doesn't call init(), then there are no guarantees as to whether client is initialized; and no guarantee as to whether the client initialized by another thread (one that did call init()) will be visible to the current thread (the one that didn't call init()).

Relying on clients to call init() first is brittle. It would be much better either to use an eagerly-initialized field:

public class DB {

private static final Client client = new Client();

public insert(Object data) {
client.insert(data); // Guaranteed to be initialized once class loading is complete.
}
}

or, if you must do it lazily, use a lazy holder:

public class DB {
private static class Holder {
private static final Client client = new Client();
}

public insert(Object data) {
Holder.client.insert(data); // Holder.client is initialized on first access.
}
}

Or, of course, chuck in a call to init() inside the insert method:

  public insert(Object data) {
init();
client.insert(data);
}

The disadvantage of the latter approach is that all threads must synchronize. In the other two approaches, there is no contention after the first invocation.

Why synchronized in static method and in Class get different java byte code

See JVM Specification §17.1 - the VM sees the 'synchronized' keyword and does the monitorenter implicitly. There are 2 ways to obtain the lock on an object in java bytecode: Either via a synchronized keyword, or via a MONITORENTER bytecode, it's as simple as that.

Difference between synchronized(this) and few synchronized methods of class

No, they are the same.

private synchronized void foo() {}

private void foo2() {
synchronized(this){
}
}

They will do the exact same as both monitor the instance which they are called from.

A good tutorial can be found in the blog of Jakob Jenkov
http://tutorials.jenkov.com/java-concurrency/synchronized.html#java-synchronized-example

Happy coding!



Related Topics



Leave a reply



Submit