Reputation: 384
I have a class defined as:
class Artifacts {
private static boolean isThreadStarted = false;
private SomeClass someClass;
public static void startThread() {
isThreadStarted = true;
}
public static void setSomeClass(SomeClass = someClass1) {
if(isThreadStarted) {
someClass = someClass1;
}
}
public static SomeClass getSomeClass() {
return someClass;
}
}
Now the use case is that a method will make the value of isThreadStarted to be true. After that, a thread will start and using the value of someClass.There can be multiple threads setting and getting the value of someClass. I want to make this thread safe.
There is an annotation @ThreadSafe
and there is a function synchronized static
which I guess will do the thing. Please help in deciding the right approach.
Upvotes: 0
Views: 105
Reputation: 7290
So, your main concern is that multiple threads will read and write the someClass
field (and maybe the isThreadStarted
field, as well).
I don't know what the @ThreadSafe
annotation does, it's not part of Java Standard Edition 8.
The basic way to make that thread-safe is to use the synchronized
keyword. Typically, you'd encapsulate access to your field in getter and setter methods and make them synchronized.
public class Test {
private String someText;
public synchronized String getSomeText() {
return someText;
}
public synchronized void setSomeText(String someText) {
this.someText = someText;
}
}
But typically the multi-thread problems aren't tied to a single field.
If different threads of your program use a (thread-shared) object, you run into the risk that one thread modifies two fields A and B (e.g. moves money from A to B by subtracting from A and adding to B), and in-between some other thread reads A and B (e.g. calculates the current amount of A plus B) and sees an inconsistent state (amount subtracted from A, but not yet added to B).
The classical solution is to ensure that of all these code sections where the instance is read or modified, only one at a time is allowed to run. And that's what synchronized
does.
Upvotes: 1
Reputation: 109
Life_Hacker,
use static synchronized keyword with function to make Class Level lock in multithreading environment.
example :
public static synchronized void setSomeClass(Artifacts.class) {
if(isThreadStarted) {
someClass = someClass1;
}
}
inside function definition, you can create Synchronize Block
example:
public static void setSomeClass(SomeClass = someClass1) {
synchronized(this){
if(isThreadStarted) {
someClass = someClass1;
}
}
}
2nd way is best approach
Upvotes: 0
Reputation: 12022
Two simple improvements you can make to make this class more threadsafe for the intended purpose are to make the someClass field volatile, and to use AtomicBoolean for the isThreadStarted field.
class Artifacts {
private static AtomicBoolean isThreadStarted = new AtomicBoolean(false);
private volatile SomeClass someClass;
The volatile will ensure that any other thread that has a reference to an Artifact instance, does not cache the someClass instance. The JVM will always retrieve the someClass field from one main source. If volatile is not used, then other threads may cache someClass and changes it it may not be reflected across all the threads that are using it.
AtomicBoolean gives you volatile feature plus atomic operations, like check and set in the same operation. Here is a excerpt from the Javadoc.
A small toolkit of classes that support lock-free thread-safe programming on single variables. In essence, the classes in this package extend the notion of volatile values, fields, and array elements to those that also provide an atomic conditional update operation of the form:
Upvotes: 1