As i understand the code below, in the synchronized block, this is an instance of a counter.
Question 1: In the example below, does this mean that when Thread A reaches the synchronized block, Thread B is blocked from doing anything to the instance of a Counter?. In other words, does this mean that Threads may continue to execute as they see please, but upon either reaches the synchronized block, the other one is stopped from doing anything to the class until the block exited?
public class Counter {
public void increment() {
// Some code
synchronized (this) { // <---- "this" is an instance of Counter
// Some more code
}
}
}
Compare code above with
public class Counter {
List<String> listOfStrings = new ArrayList<String>();
public void increment() {
// Some code
synchronized (listOfStrings) {
// Some code that deals with
// listOfStrings
}
}
}
Question 2: In the example above, once Thread A reaches the synchronized block, Thread B may continue reading and writing anything in the class with the exception of listOfStrings ArrayList, which is a mutex in the synchronized block. Is this correct?
Question 3: Is it further correct to assume that if we need to make modifications to multiple objects, this is the mutex we should use?
For example:
public class Counter {
List<String> listOfStrings = new ArrayList<String>();
List<Integers> listOfIntegers = new ArrayList<Integers>();
public void increment() {
// Some code
synchronized (this) {
// Some code that deals with
// listOfStrings and listOfIntegers
}
}
}
Am i understanding things correctly? Please correct if i misstated anything.
No, Thread B is blocked from entering the synchronized blocks of code, it can still enter other methods: those that are not synchronized and those synchronized using different objects. Thread B cannot only access blocks synchronized using an object already taken by a different thread (synchronized locks are re-entrant).
Not really, that fact that
listOfStringsis used as a mutex in onesynchronizedblock does not mean other threads cannot access that object explicitly. It only means that other thread cannot access synchronized blocks guarded by the same object. So if you want to secure access tolistOfStringsobject, all methods accessing that object must be synchronized and use the same lock (e.g.listOfStrings).BTW every object you synchronize on should be
finalto avoid headaches.Yes and no. Consider the following case:
If one method only accesses lists and the second method only accesses sets, you can safely use two locks – one for the first method and second one for the second method. Synchronizing on
thiswon’t hurt, but it will impact performance:and later: