I have a class:
class Station {
public void decrement(){
// ...
}
}
There are two different instances of it: station1 and station2. The function decrement() gets called on station1 and station2 by two different threads. I want to synchronize decrement() over all objects and threads.
As per what I read, synchronized keyword synchronizes the calls of a function of one single object, so it won't work here. How do I synchronize calls across all instances of Station?
synchronized object instead. Example:
class Station {
private final static Object DECREMENT_LOCKER = new Object();
public void decrement(){
synchronized (DECREMENT_LOCKER) {
//do smt
}
}
}
Related
mFeaute is a mutable object.
I want to know if the change of mFeature in setFeature(Feature feature) is visible to mFeature in useFeature(...) with a different explicit form of synchronized.
Thanks.
public class FeatureService {
private static Feature mFeature= null;
private final Object MUTEX = new Object();
...
static void setFeature(Feature feature){
// doSomething
synchronized (FeatureService.class){
mFeature = feature;
// doSomething
}
// doSomething
}
public void useFeature(...){
// doSomething
synchronized (MUTEX){
someFunction(mFeature);
// doSomething
}
// doSomething
}
}
}
The above code is suffering from a data race and hence is broken. You do not have a happens before edge between the write and the read of mfeature because different locks are used. You need to use the same lock instance for both reading and writing.
It is unclear what you are trying to synchronize on (ClassA and ObjectB are vague). In general, you want to synchronize on a single mutex when interacting with a given shared resource. Create an Object to serve as the mutex upon which you synchronize when accessing the internal mFeature.
public class FeatureService {
private static Feature mFeature= null;
private static final Object MUTEX = new Object();
...
static void setFeature(Feature feature){
synchronized (MUTEX){
mFeature = feature;
}
}
public void useFeature(...){
synchronized (MUTEX){
someFunction(mFeature);
}
}
}
Question 1.
If we consider the following class:
public class Test {
public static LinkedList<String> list;
}
How would you make getting/setting thread-safe for the variable 'list'?
I guess I could do something like this:
public class Test {
private static LinkedList<String> list;
public static synchronized LinkedList<String> getList() {
return new LinkedList<>(list);
}
public static synchronized void setList(LinkedList<String> data) {
list = new LinkedList<>(data);
}
}
Question 2.
But how thread-safe is this? Would I have to initialize a new list each time to ensure other copies don't affect the variable?
Question 3.
If we consider this instead:
public class Test {
private static LinkedList<String> list;
public static synchronized void ManipulateList() {
// do stuff to 'list'
}
public static synchronized void ChangeList() {
// do more stuff to 'list'
}
}
where both methods 'ManipulateList' and 'ChangeList' might add or remove variables to the same list
Is this thread-safe? Does this mean that if thread 1 is accessing 'ManipulateList' then thread 2 is not able to access 'ChangeList' until thread 1 finishes accessing 'ManipulateList'?
I'm just not sure if I'm understanding the effects correctly.
Question 1.
public static LinkedList<String> list;
How would you make getting/setting thread-safe for the variable
'list'?
Avoid global [mutable] state. Just get rid of it.
Question 2.
public class Test {
private static LinkedList<String> list;
public static synchronized LinkedList<String> getList() {
return new LinkedList<>(list);
}
public static synchronized void setList(LinkedList<String> data) {
list = new LinkedList<>(data);
}
}
But how thread-safe is this? Would I have to initialize a new list
each time to ensure other copies don't affect the variable?
(I am going to assume by this you mean Test.list not the passed in data which, due to the defects of the Java collection library, is mutable itself.
So you are always accessing the list with the same lock held. You are always copying the list when dealing with the outside world. The members of the list are immutable, so you don't need any deep copying. All good.
The method have the lock held over an expensive operation not involving the variable, so we should do better here.
public static synchronized LinkedList<String> getList() {
// The `LinkedList` list points to is never mutated after set.
LinkedList<String> local;
synchronized (Test.class) {
local = list;
}
return new LinkedList<>(local);
}
public static void setList(LinkedList<String> data) {
LinkedList<String> local = new LinkedList<>(data);
synchronized (Test.class) {
list = local;
}
}
In theory, even without the change the lock needn't be held continuously for the entire copy. As it is a public lock object (but naughty, but common) data could wait on it releasing the lock temporarily. Obviously not significant here, but in real world cases it may lead to strangeness.
Slightly more obscurely, list could be made volatile and the lock elided.
Question 3.
private static LinkedList<String> list;
public static synchronized void ManipulateList() {
// do stuff to 'list'
}
public static synchronized void ChangeList() {
// do more stuff to 'list'
}
Is this thread-safe? Does this mean that if thread 1 is accessing
'ManipulateList' then thread 2 is not able to access 'ChangeList'
until thread 1 finishes accessing 'ManipulateList'?
Yes. Other than there may be waits and one of the methods could call the other, perhaps indirectly.
General notes.
Remove global [mutable] state.
Try to avoid shared mutable object (keep shared object immutable and mutable objects unshared).
Reduce the amount of code and time that locks are held for.
Copy mutable inputs and outputs.
I guess I could do something like this:
This isn't thread safe.
Specifically, the setter:
public static synchronized void setList(LinkedList<String> data) {
list = new LinkedList<>(data);
}
does not enforce that data is accessed exclusively for the duration of the setList method. As such, other threads could modify the list during the implicit iteration.
The code in question 3 is fine with respect to updates to the list, because the fact the methods are synchronized means that the list is accessed mutually exclusively, and the effects of one method invocation are visible to subsequent invocations.
But it's not entirely safe, because nefarious code can acquire (and hold onto) the monitor of Test, which could lead to a deadlock.
You can fix this specific issue by having an explicit monitor that can only be acquired inside the class:
class Test {
private final Object obj = new Object();
public static void ManipulateList() {
synchronized (obj) { ... }
}
public static void ChangeList() {
synchronized (obj) { ... }
}
}
Anything that subclasses your Test class could break your synchronization scheme because subclasses could directly access the list without the method-synchronization - either by subclassing your Test class or through reflection.
public class MyTestClass extends Test {
// blah...
public static changeTheList() {
this.list.add("Bypasses synchronization through direct access to the list.");
}
}
A better solution for synchronization is to initialize your list with a synchronized wrapper, like this:
public class Test {
private static LinkedList<String> list = Collections.synchronizedList(new LinkedList<>());
public static synchronized LinkedList<String> getList() {
return list;
}
public static synchronized void setList(LinkedList<String> newList) {
list = newList;
}
}
In the second snippet, you can now safely sub-class your Test class and access the list in a thread-safe manner because the list itself is synchronized.
You other option is to mark your Test class as final but you would still need to fix your implementation (you re-initialize the list in your getter's & setter's which is not a good idea).
Also -- I might suggest you look at some tutorials regarding synchronization -- a couple of suggestions:
https://www.baeldung.com/java-synchronized-collections
https://howtodoinjava.com/java/collections/arraylist/synchronize-arraylist/
I have a class like this one:
public class IClass{
public void draw(){...}; //is called periodically by the rendering thread
public void foo(){...}; //is called asynchronously from another Thread(it could be an onTouchEvent() method for example)
}
I want the foo() method to wait until the draw method is finished and vice versa. How can I do this in Java?
regards
Make the methods synchronized.
public synchronized void draw() { System.out.println("draw"); }
public synchronized void foo() { System.out.println("foo"); }
Or synchronize on the same object.
private static final Object syncObj = new Object();
public void draw() {
synchronized (syncObj) {
System.out.println("draw");
}
}
public void foo() {
synchronized (syncObj) {
System.out.println("foo");
}
}
Putting synchronized on a method means the thread has to acquire the lock on the object instance before entering that method, so if you have two different methods marked synchronized the threads entering them will be contending for the same lock, and once one thread gets the lock all other threads are shut out of all methods that synchronize on that same lock. So in order for the two methods to run concurrently they would have to use different locks, like this:
public class IClass {
private final Object lockDraw = new Object();
private final Object lockFoo = new Object();
public void draw() {
synchronized(lockDraw) {
//method draw
}
}
public void foo() {
synchronized(lockFoo) {
//method foo
}
}
}
Both methods lock the same monitor. Therefore, you can't simultaneously execute them on the same object from different threads (one of the two methods will block until the other is finished).
public synchronized int getCountOne() {
return count++;
}
Like in above code synchronizing on the method is functionally equivalent to having a synchronized (this) block around the body of the method. The object "this" doesn't become locked, rather the object "this" is used as the mutex and the body is prevented from executing concurrently with other code sections also synchronized on "this."
On similar grounds what is used as a mutex when we acquire a class level lock.As in if we have a function
public static synchronized int getCountTwo() {
return count++;
}
obviously two threads can simultaneously obtain locks on getCountOne(object level lock) and getCountTwo(class level lock). So as getCountOne is analogous to
public int getCountOne() {
synchronized(this) {
return count++;
}
}
is there an equivalent of getCountTwo? If no what criteria is used to obtain a Class level lock?
On similar grounds what is used as a mutex when we acquire a class level lock
The class object itself will be used as mutex. The equivalent synchronized block for your static synchronized method will look like:
public static int getCountTwo() {
synchronized(ClassName.class) {
return count++;
}
}
ClassName is the name of the class containing that method.
See JLS Section §8.4.3.6:
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.
Emphasis mine.
Object level locking:
Object level locking is mechanism when you want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on given instance of the class. This should always be done to make instance level data thread safe. This can be done as below :
public class DemoClass
{
public synchronized void demoMethod(){}
}
or
public class DemoClass
{
public void demoMethod(){
synchronized (this)
{
//other thread safe code
}
}
}
or
public class DemoClass
{
private final Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
Class level locking:
Class level locking prevents multiple threads to enter in synchronized block in any of all available instances on runtime. This means if in runtime there are 100 instances of DemoClass, then only one thread will be able to execute demoMethod() in any one of instance at a time, and all other instances will be locked for other threads. This should always be done to make static data thread safe.
public class DemoClass
{
public synchronized static void demoMethod(){}
}
or
public class DemoClass
{
public void demoMethod(){
synchronized (DemoClass.class)
{
//other thread safe code
}
}
}
or
public class DemoClass
{
private final static Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
}
What would be the behaviour of the following program where static synchronized method and instance synchronized method is trying to access static field of same class in different threads? Will any thread get blocked? Its very confusing.
class MyClass
{
public static int i = 5;
public synchronized void m1()
{
System.out.println(i); //uses static field i of MyClass
//T1 is executing this method
}
public static synchronized void m3()
{
//T2 will be able to call this method on same object lock while it is using
//static field i???
System.out.println(i);//uses static field i of MyClass
}
}
Synchronized instance methods are equivalent of
public void m1() {
synchronized(this) {
...
}
}
(well, they are not exactly the same, but the answer to your question does not suffer from that difference).
Synchronized static methods are synchronized on the class:
public void m2() {
synchronized(MyClass.class) {
...
}
}
As you can see, two block are synchronized on difference objects: m1 is synchronized on the instance it is called on, and m2 is synchronized on the instance of Class<MyClass> which represents your class in JVM. So those two methods can be called without blocking each other.
You are always synchronizing on an object.
Funciton m1 synchronizes on an instance of an object on which it is called.
Function m3 synchronizes on the class itself.
m1 could be written as:
public void m1()
{
synchronized(this) {
System.out.println(i); //uses static field i of MyClass
//T1 is executing this method
}
}
Therefore you are synchronizing on two different objects and these two methods can acces any global variable concurrently.
Your sample code looks good.
Best way to assure synchronization of static variables according to me is. As lock object is not accessible outside your Class. See below.
public class MyClass
{
private static int i = 0;
private static final Object lockObject = new Object();
public void m1() {
synchronized (lockObject ) {
//Use you static var
}
}
public void m3() {
synchronized (lockObject ) {
//Use you static var
}
}
}
The method m1 and m3 can be executed independently.
Because as you already said static synchronized is on the object. Therefore the same as synchronize(MyClass.class).
synchronized are instance wide usable. So it is only blocked for the instances. It would be the same as using:
MyClass myClass = new MyClass();
synchronize (myClass)
{
.....
}
Java does not have any synchronization controls that relate to accessing static fields.
If you make your methods empty, the synchronization will be exactly the same.
Specifically, as long as any thread is executing any synchronized static method in that type, all other threads that call synchronized static methods will wait for them to finish, so that at most one synchronized static method will be executing at once.