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.
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++;
}
}Explicitly synchronize on the class object.
public class Test {
private static int count = 0;
public void incrementCount() {
synchronized (Test.class) {
count++;
}
}
}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 toclient
is has happened before the current thread enters thesynchronized
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
Parsing an Arithmetic Expression and Building a Tree from It in Java
Java Count Occurrence of Each Item in an Array
How to Iterate Through the Unicode Codepoints of a Java String
How Does Java Do Modulus Calculations with Negative Numbers
Read Content from Files Which Are Inside Zip File
The Literal Xyz of Type Int Is Out of Range
Java Stack Overflow Error - How to Increase the Stack Size in Eclipse
How to Count the Number of Matches for a Regex
Creating a Variable Name Using a String Value
How to Parse Output of New Date().Tostring()
Java Datetimeformatterbuilder Fails on Testtime
How to Read an External Properties File in Maven
Spring Boot, Spring Data JPA with Multiple Datasources
Failed to Run Sdkmanager --List with Java 9
Android M Permissions: Onrequestpermissionsresult() Not Being Called