I've come across code like the following several times
class Foo {
private Object lock = new Object();
public void doSomething() {
synchronized(lock) {
...
What I'm interested in is why a lock object is created instead of writing synchronized(this)? Is it there to enable sharing the lock? I vaguely remember reading that it is an optimization. Is that true? Also, does it, in some context, make sense to have the lock declared as final?
Synchronizing on this is discouraged because if the object itself is used as a lock from the outside it would break the internal synchronization. Also, remember that synchronized methods are also using this as a lock, which may cause an unwanted effect.
Declaring the lock final is recommended to prevent a situation in which a lock object is reassigned inside a synchronized block, thus causing different threads to see different lock objects. See this other question: Locking on a mutable object - Why is it considered a bad practice?
Imagine a scenario where you have thread1 and thread2 access method1, thread3 and thread4 access method2. Synchronizing on this would block thread3 and thread4 if thread1 or thread2 are accessing method1 which should not happen as thread3 and thread4 have nothing to do with method1. An optimization for this is to use two different locks instead of locking on the whole class instance.
Here is a nice paragraph I found on JavaDoc that reflects this:
Synchronized statements are also useful for improving concurrency with
fine-grained synchronization. Suppose, for example, class MsLunch has
two instance fields, c1 and c2, that are never used together. All
updates of these fields must be synchronized, but there's no reason to
prevent an update of c1 from being interleaved with an update of c2 —
and doing so reduces concurrency by creating unnecessary blocking
Consider using a lock from the java.util.concurrent package
This may provide more optimized locking, for instance - using a ReadWriteLock will let all readers to access without waiting.
Here is the Full working example of "ReentrantReadWriteLock".
public class DataReader {
private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static final Lock read = readWriteLock.readLock();
private static final Lock write = readWriteLock.writeLock();
public static void loadData() {
try {
write.lock();
loadDataFromTheDB());
} finally {
write.unlock();
}
}
public static boolean readData() {
try {
read.lock();
readData();
} finally {
read.unlock();
}
}
public static List loadDataFromTheDB() {
List list = new ArrayList();
return list;
}
public static void readData() throws DataServicesException {
//Write reading logic
}
}
Related
If I have a class that has 2 methods say setA and setB that have synchronized but they are not synchronized on the same object, how do I lock it such that if there were two instances of the class, methods setA and setB cannot happen simultaneously?
In short, you can use a synchronized (lockObj) {...} block in the body of both methods, and use the same lockObj instance.
class MyClass {
private final Object lock;
public MyClass(Object lock) {
this.lock = lock;
}
public void setA() {
synchronized (lock) {
//...
}
}
public void setB() {
synchronized (lock) {
//...
}
}
}
Few things to note:
The lock needs not to be static. It is up to your implementation how you provide it. But every MyClass instance must use the same lock instance if you want them to prevent threads from executing their blocks simultaneously.
You can not use synchronized methods in this case, since each non static synchronized method will use its on this instance's monitor.
If you want to access other instance members, you can not use static synchronized methods either.
You can still synchronize on another object within the class that you create.
Object lock = new Object();
Then just synchronize on the lock object.
If you want to get a bit more into it you can use the util.concurrency libraries.
Check out Semaphores or Latches, depends on what you want to do with your setA and setB
Multiple ways.
1) You can synchronize the methods: public synchronized void setA()
Doing that means that only one thread can enter the method at a time (good and bad)
2) A better solution would be to use a ReentrantLock:
ReentrantLock lock = new ReentrantLock();
void public void setA() {
lock.lock();
try {
//Do Something
}
finally {
lock.unlock();
}
}
There are other ways as well.
You can check the Java tutorial on concurrency:
https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Another decent posting:
http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
Good luck!
Synchronize them on a single, static reference. A private static final Object lock = new Object () will do, as Will just TheClass.class.
This will also mean that no two threads can invoke setA at the same time, even if nobody is invoking setB. If that's not acceptable, you can use a (static) read-write lock for finer-grained access. setA uses the read lock, and setB uses the write lock; that means that any number of threads can invoke setA, but only one can invoke setB. You probably don't want the reverse to also be true, because that's susceptible to deadlocking.
I have less experience of multi-thread programming. I have multi-threads to write to a file. And I was wondering what's the difference between:
Implement 1: a class with static synchronized function. And each thread call FileUtil.writeToFile()
public class FileUtil {
public static synchronized void writeToFile(String filename) {
// write to file....
}
}
Implement 2: A singleton class. And each thread call Fileutil.getInstance().writeToFile()
public class FileUtil {
private static final FileUtil fileManager = new FileUtil();
private FileUtil() {
}
public synchronized void writeToFile(String filename) {
// write to file....
}
public static FileUtil getInstance() {
return fileManager;
}
}
There is no practical difference.
In practice, either way, you have one unique lock object that all callers must acquire in order to enter the method.
The only difference is the identity of the lock object: In the singleton case, the lock object is the singleton. In the static method case, it's the Class object.
The issues in your question can be divided into:
Should I use a class with static methods or the singleton pattern? This has already been discussed, for example in Difference between static class and singleton pattern?.
Is there a difference between the two synchronizations? Well, one locks on a class, the other on an object. And as Sotirios Delimanolis linked in the comments, it's discussed in Java synchronized static methods: lock on object or class.
Regarding the choice of monitor, there is a third option:
Use a monitor object that is not accessible to the caller. The advantage of this is that if the user of the class or the singleton decides to use that class or that singleton as a monitor in his own program, it won't cause all calls to writeToFile() to be blocked.
That is, suppose somebody does this:
FileUtil obj = FileUtil.getInstance();
synchronized ( obj ) {
// Some long operation
}
Because the writeToFile() method synchronizes on that same instance, no other thread will be able to use writeToFile() until the "long operation" is done and the synchronized block is left.
Now, instead, if you did this:
public class FileUtil {
private static final FileUtil fileManager = new FileUtil();
private static final Object lock = new Object(); // To be used for synchronizing
private FileUtil() {
}
public void writeToFile(String filename) {
synchronized (lock) {
// write to file....
}
}
public static FileUtil getInstance() {
return fileManager;
}
}
then even if the user of your class decides to use it as a lock (be it the class monitor or an instance monitor), it's not going to interfere with the functionality of writeToFile().
In short, there is no real difference.
The thing to note here is that in synchronization number 1 (static synchronized method), all threads would compete on acquiring the lock on the Class object (that represents the FileUtil class) and only one thread will acquire the lock at a time and execute the method.
In the second case all threads would again compete on acquiring the monitor associated with the "this" object (and only one thread will acquire it and execute at a time). Note we are talking about a singleton so there is exactly one instance in this address space (there could be more than one instance if this class is loaded through more than one classloaders as well but we digress).
In either case all the threads are competing to acquire a lock on exactly one object: the class description object or the "this" object and therefore there is no real difference when you run the program. There is a slight heap difference in that an instance of the FileUtil is created in the second case and put on the heap but that is inconsequential.
Both are equivalent in delivering the same result.
But I prefer second implementation of Singleton class + RealSkeptic suggestion to have static final lock object.
Advantage with Singleton : In future, you can change Singleton to ObjectPool of FileUtil with a certain size (e.g.: 5 objects of FileUtil). You have more control with pool of FileUtil with static Object lock compared to static synchronized method in first implementation.
If I have the following code
class SomeClass {
...
public synchronized methodA() {
....
}
public synchronized methodB(){
....
}
}
This would synchronized on the 'this' object.
However, if my main objective here is to make sure multiple threads don't use methodA (or methodB) at the same time, but they CAN use methodA AND methodB concurrently,
then is this kind of design restrictive? since here thread1 lock the object (monitor object associated with the object) for running methodA but meanwhile thread2 is also waiting on the object lock even though methodA and methodB can run concurrently.
Is this understanding correct?
If yes, is this the kind of situation where we use synchronized block on a private dummy object so that methodA and methodB can run parallely with different thread but not methodA (or methodB) with different threads.
Thanks.
You've answered the question yourself: use one lock object per method and you're safe.
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized(lockA){
....
}
}
public void methodB() {
synchronized(lockB){
....
}
}
For more advanced locking mechanisms (e.g. ReentrantLock), read Java Concurrency in Practice by Brian Goetz et al. You should also read Effective Java by Josh Bloch, it also contains some items about using synchronized.
If you want to allow running methodA() and methodB() concurrently but otherwise restrict each method to one thread then you need two separate objects to synchronize on. For instance:
class SomeClass {
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized (lockA) {
//
}
}
public void methodB() {
synchronized (lockB) {
//
}
}
}
If my understanding is correct you want to allow thread T1 to run methodA() at the same time thread T2 runs methodB() -- but you don't want thread T1 to run methodA() at the same time thread T2 runs methodA() (and same for methodB) right?
For this scenario you can't use just a simple synchronized method -- instead, as you said, you will need 2 dummy objects (one for methodA and one for methodB) to synchronize on. Or you could use the new Lock class -- one Lock instance per method.
I want to understand how locking is done on static methods in Java.
let's say I have the following class:
class Foo {
private static int bar = 0;
public static synchronized void inc() { bar++; }
public synchronized int get() { return bar; }
It's my understanding that when I call f.get(), the thread acquires the lock on the object f and when I do Foo.inc() the thread acquires the lock on the class Foo.
My question is how are the two calls synchronized in respect to each other?
Is calling a static method also acquires a lock on all instantiations, or the other way around (which seems more reasonable)?
EDIT:
My question isn't exactly how static synchronized works, but how does static and non-static methods are synchronized with each other.
i.e., I don't want two threads to simultaneously call both f.get() and Foo.inc(), but these methods acquire different locks. My question is how is this preventable and is it prevented in the above code.
Static and instance synchronized methods are not related to each other, therefore you need to apply some additional synchronization between them, like this:
class Foo {
private static int bar = 0;
public static synchronized void inc() { bar++; }
public synchronized int get() {
synchronized (Foo.class) { // Synchronizes with static synchronized methods
return bar;
}
}
}
(though in this case leaving synchronized on get() doesn't make sense, since it doesn't do anything that requires synchronization on instance).
Beware of deadlocks - since this code aquires multiple locks, it should do it in consistent order, i.e. other synchronized static methods shouldn't try to acquire instance locks.
Also note that this particular task can be solved without synchronization at all, using atomic fields:
class Foo {
private static AtomicInteger bar = new AtomicInteger(0);
public static void inc() { bar.getAndIncrement(); }
public int get() { return bar.get(); }
}
A synchronized static method is effectively equivalent to:
public static void foo() {
synchronized (ClassName.class) {
// Body
}
}
In other words, it locks on the Class object associated with the class declaring the method.
From section 8.4.3.6 of the JLS:
A synchronized method acquires a monitor (§17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
If you read http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html.
It will tell you:
You might wonder what happens when a
static synchronized method is invoked,
since a static method is associated
with a class, not an object. In this
case, the thread acquires the
intrinsic lock for the Class object
associated with the class. Thus access
to class's static fields is controlled
by a lock that's distinct from the
lock for any instance of the class.
which tells you all you need to know.
Neither, the non-static synchronized call does not acquire a lock on the class itself. (And the static synchronized block does not lock any object instantiated from that class.)
In other words the calls f.get() (locks f) and Foo.inc() (locks the class Foo) can run concurrently. They are not "synchronized".
You could use a different pattern (singleton), or make all the methods static.
Static locks are attached to the class definition and thus is shared between all instances of that class.
Synchronization of none static methods only apply to the current instance of the class (the lock is on the class instance, e.g., this). In your example you have two different locks with no interrelation.
I don't want two threads to simultaneously call both f.get() and Foo.inc(), but these methods acquire different locks. My question is how is this preventable and is it prevented in the above code
You must share a lock to be able to arbitrate access to both f.get and Foo.inc(). You can do this either by sharing the same static lock or by the same instance lock.
These two calls do not synchronize in respect to each other.
It is as you said, a caller of f.get() acquires the lock of f object and caller of Foo.inc() acquires Foo.class object's one. So the synchronization rules are the same as if instead of static call you called an instance synchronized method with another object.
I know when you want to lock method to be executed by only one thread you declare it with synchronized keyword.
What about classes, how to provide a lock on an entire class of objects when a thread
is executing some code on an instance of that class?
In other words, when a thread is executing a method on an object, no other thread should be
allowed to execute the same method even on a different instance of the same class.
You synchronize on a specific object, either some designated static lock object, or the class object (which happens when static methods are declared to be synchronized):
class X {
private static final Object lock = new Object();
public void oneAtATime() {
synchronized (lock) {
// Do stuff
}
}
}
class Y {
public void oneAtATime() {
synchronized (Y.class) {
// Do stuff
}
}
}
Each variant has its own pros and cons; locking on the class allows other code, outside of the class, to use the same lock for its own reasons (which allows it to orchestrate more high-level synchronization than what you provide) while the static final Object lock approach lets you prohibits it by making the lock field private (which makes it easier to reason about the locking and avoid your code from deadlocking because someone else wrote bad code).
You could of course also use some synchronization mechanism from java.util.concurrent, like explicit Locks, which provide more control over locking (and ReentrantLock currently performs a little better than implicit locks under high contention).
Edit: Note that static/global locks aren't a great way to go - it means every instance of the class ever created will essentially be tied to every other instance (which, aside from making it harder to test or read the code, can severely harm scalability). I assume you do this to synchronize some kind of global state? In that case, I'd consider wrapping that global/static state in a class instead, and implement synchronization per-instance rather than globally.
Instead of something like this:
class Z {
private static int state;
public void oneAtATime(){
synchronized (Z.class) {
state++;
}
}
}
Do it like this:
class State {
private int value;
public synchronized void mutate(){ value++; }
}
class Z {
private final State state;
public Z(State state){
this.state = state;
}
public void oneAtATime(){
state.mutate();
}
}
// Usage:
State s1 = new State(), s2 = new State();
Z foo = new Z(s1);
Z bar = new Z(s1);
Z frob = new Z(s2);
Z quux = new Z(s2);
Now foo and bar are still tied to each other, but they can work independently from frob and quux.
If you use static synchronized methods, they are locked via the Class Lock. You can also declare a static Object in the class and lock that in a method I believe via something like:
private static final Object STATIC_LOCK = new Object();
private void foo() {
synchronized (STATIC_LOCK) {
//do stuff...
}
}
You could use a static Mutex inside that method. So any concurrent thread is blocking inside the method while another is running it no matter what object of the class it belongs to. I don't think there is any special single keyword to produce the same effect like synchronized.
It is a rather aggressive synchronization, I would avoid it as much as possible.
Synchronize on static field of your class, or the class itself:
synchronized(MyClass.class) {
// mutually excluded method body
}
Both threads must use this construction
public void someMethod() {
synchronized(ClassThatShouldBeProtected.class) {
someSynchronizedCode();
}
}
This approach benefits from the fact, that class itself is an object and therefore it has a monitor. Then you don't need any artificial static instance.
There is no built-in mechanism for this. Create your own static lock attribute, and make sure you lock it and unlock it in every method. Don't forget about exceptions - make sure you unlock it in the "finally" sections.
This should work:
public class MyClass {
void synchronizedMethod() {
synchronized (MyClass.class) {
// synchronized on static level
}
}
}
Which 'missuses' the class's runtime-representation for locking. This is possible as any object can be used as a mutex in Java.
http://www.janeg.ca/scjp/threads/synchronization.html
talks about several ways to achieve it.
in general, locks are prohibitive and hinder benefits of threading. so the critical code should be minimized as much as its possible.
do you want a class lever lock to access static variables of the class or is it for protecting access to a common external resource the class? in which case you should proly have a separate lock while accessing it.