My IDE (JetBrains IntelliJ IDEA) warns me about synchronizing on a method parameter even when it's always an object.
The full warning reads:
Synchronization on method parameter 's' ... Inspection
info: Reports synchronization on a local variable or parameter. It is
very difficult to guarantee correctness when such synchronization is
used. It may be possible to improve code like this by controlling
access through e.g. a synchronized wrapper class, or by synchronizing
on a field.
My guess is that with auto-boxing, the parameter might be a primitive which gets converted to an object? Although, with auto-boxing, I would assume it's always an object, but maybe not a shared object which means it wouldn't be shared synchronization.
Anyone know why the warning would be present? In my case ShortCircuit type is always an object and the IDE should be able to know that.
The thing is that if you forget to synchronize on ShortCircuit when using it in other places of your code you might get unpredictable results. It's a lot better to synchronize inside the ShortCircuit class so it's guaranteed to be thread safe.
Update
If you're moving the synchronization outside of the class it's inherently unsafe for threading. If you want to synchronize on it externally you will have to audit all places it's used, that's why you get the warning. It's all about good encapsulation. It will be even worse if it is in a public API.
Now if you move the fireFinalCallback method to your ShortCircuit class you can guarantee that the callback won't fire simultaneously. Otherwise you need to have this in mind when calling the methods on that class.
As jontro already mentioned in his answer (and basically, as the warning already says) : This sort of synchronization on the ShortCircuit object does not have the effect that the developer probably hoped to achieve. Unfortunately, the tooltip in your screenshot hides the actual code, but it seems like the code could roughly be
synchronized (s)
{
if (!s.isFinalCallbackFired())
{
s.doFire();
}
}
That is: It is first checked whether isFinalCallbackFired returns false, and if this is the case, something (hidden) is done, which likely causes the isFinalCallbackFired state to switch to true.
So my assumption is, roughly, that the goal of putting the if statement into the synchronized block was to make sure that doFire is always called exactly once.
And indeed, at this point, the synchronization could be justified. More specifically, and a bit oversimplified:
What can be guaranteed:
When two threads are executing the fireFinalCallback method with the same ShortCircuit parameter, the synchronized block will guarantee that only one thread at a time can check the isFinalCallbackFired state and (if it is false) call the doFire method. So it is guaranteed that doFire will be called only once.
What can not be guaranteed:
When one thread is executing the fireFinalCallback method, and another thread does any operation on the ShortCircuit object (like calling doFire), then this might lead to an inconsistent state. Particularly, if another thread also does
if (!s.isFinalCallbackFired())
{
s.doFire();
}
but without synchronizing on the object, then doFire may be called twice.
The following is an MCVE that illustrates the effect:
public class SynchronizeOnParameter
{
public static void main(String[] args)
{
System.out.println("Running test without synchronization:");
runWithoutSync();
System.out.println();
System.out.println("Running test with synchronization:");
runWithSync();
System.out.println();
System.out.println("Running test with wrong synchronization:");
runWithSyncWrong();
System.out.println();
}
private static void runWithoutSync()
{
ShortCircuit s = new ShortCircuit();
new Thread(() -> fireFinalCallbackWithoutSync(s)).start();
pause(250);
new Thread(() -> fireFinalCallbackWithoutSync(s)).start();
pause(1000);
}
private static void runWithSync()
{
ShortCircuit s = new ShortCircuit();
new Thread(() -> fireFinalCallbackWithSync(s)).start();
pause(250);
new Thread(() -> fireFinalCallbackWithSync(s)).start();
pause(1000);
}
private static void runWithSyncWrong()
{
ShortCircuit s = new ShortCircuit();
new Thread(() -> fireFinalCallbackWithSync(s)).start();
if (!s.isFinalCallbackFired())
{
s.doFire();
}
}
private static void fireFinalCallbackWithoutSync(ShortCircuit s)
{
if (!s.isFinalCallbackFired())
{
s.doFire();
}
}
private static void fireFinalCallbackWithSync(ShortCircuit s)
{
synchronized (s)
{
if (!s.isFinalCallbackFired())
{
s.doFire();
}
}
}
static class ShortCircuit
{
private boolean fired = false;
boolean isFinalCallbackFired()
{
return fired;
}
void doFire()
{
System.out.println("Calling doFire");
pause(500);
fired = true;
}
}
private static void pause(long ms)
{
try
{
Thread.sleep(ms);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
The output is
Running test without synchronization:
Calling doFire
Calling doFire
Running test with synchronization:
Calling doFire
Running test with wrong synchronization:
Calling doFire
Calling doFire
So the synchonized block does make sure that the doFire method is only called once. But this only works if all modifications are only done in the fureFinalCallback method. If the object is modified elsewhere, without a synchronized block, the doFire method may be called twice.
(I'd like to offer a solution for this, but without details about the ShortCircuit class and the remaining classes and processes, one could only give the vague hint to have a look at the java.util.concurrent package and its subpackages: Locks and Conditions might be a viable path, but you have to figure that out...)
Related
Concurrent collection:
ConcurrentMap<LocalDate, A> ex = new ConcurrentHashMap<>();
class A {
AtomicLong C;
AtomicLong D
}
How can I synchronize by locking "C" and "D"? That is, I need to change "C" and "B" at the same time with a guarantee that while I change the other one, the first one does not change from external actions.
Thank you.
What you're solving for
You are describing that you want to:
allow a caller to modify something on an object
prevent any other callers (other threads) from modifying things at the same time
Solution description
This solution uses synchronized, though there are number of other mechanisms available in Java that would support this (several of which are covered in
the Lock Objects section of the Java Tutorials).
The way "synchronized" works is that you designate some code using the "synchronized" keyword, along with an object to synchronize on.
When your code runs, the JVM will guarantee that, for all code which is synchronized – on the same object – only one thread
can proceed at a time.
You can make a synchronized code block, like below. Note: this defines an Object named "lock", but it's just a name chosen for clarity when
reading the code – you could name it anything you like.
Object lock;
synchronized (lock) {
... // all things here run only when "lock" is available
}
You can also designate an entire method as being synchronized, like this:
public void synchronized print() {
System.out.println("hello");
}
This second example behaves like the first - it also locks on an object – but it's not clear at a glance what the object is; that is, how does
the JVM know which object to sychronize on? This approach works if the method itself is called on an object instance, and in that case the lock becomes this. I'll show an example below.
There's good info in the Java Tutorials about synchronized methods.
Solution #1: synchronized block using Object lock
Here are a few notes about a class AllowOneEditAtATime:
it has two private members: one and two
because they're private, they cannot be changed directly – so it would not be allowed to do something like this:
AllowOneEditAtATime a = new AllowOneEditAtATime();
a.one = new AtomicLong(1); // cannot change "one" directly because it is private
defines private Object lock – this is meant to act as the thing that two different synchronized code blocks will lock on. It's totally fine to have different blocks of code each synchronize on the same object. This is the main technique you're after.
uses a synchronized block inside setOne(), synchronizing on "lock"
uses another synchronized block inside the other method – setTwo() – also synchronizing on "lock"
because both setOne() and setTwo() are synchronized on the same object, one of them will be allowed to run at a time
class AllowOneEditAtATime1 {
private Object lock;
private AtomicLong one;
private AtomicLong two;
public void setOne(AtomicLong newOne) {
synchronized (lock) {
one = newOne;
}
}
public void setTwo(AtomicLong newTwo) {
synchronized (lock) {
two = newTwo;
}
}
}
Solution #2: synchronized block, using this
Solution #1 works fine, but it isn't necessary (in this case) to create an entire object just for locking. Instead, you can rely on the fact that
this code runs only after someone called new AllowOneEditAtATime(), which means there's always an object instance, which means inside the code
you can use this. The this keyword refers to the object instance itself, the actual instance of AllowOneEditAtATime.
So here's a variation using this (no more Object lock):
class AllowOneEditAtATime2 {
private AtomicLong one;
private AtomicLong two;
public void setOne(AtomicLong newOne) {
synchronized (this) {
one = newOne;
}
}
public void setTwo(AtomicLong newTwo) {
synchronized (this) {
two = newTwo;
}
}
}
Solution #3: synchronized methods, implicit lock
Solution #2 works fine, but since we're using this as the lock, and since the code paths fit with doing this, we can use
synchronized methods
instead of synchronized code blocks.
That means we can replace this:
public void setTwo(AtomicLong newTwo) {
synchronized (this) {
two = newTwo;
}
}
with this:
public synchronized void setOne(AtomicLong newOne) {
one = newOne;
}
Under the covers, the entire setOne() method is synchronized on this automatically, so it isn't necessary to
include synchronized (this) { .. }
at all. In Solution #2, both methods were doing that, so both can be replaced.
By synchronizing both methods, they will both be synchronized on the object instance (this), which is similar to Solution #2, but with less code.
class AllowOneEditAtATime3 {
private AtomicLong one;
private AtomicLong two;
public synchronized void setOne(AtomicLong newOne) {
one = newOne;
}
public synchronized void setTwo(AtomicLong newTwo) {
two = newTwo;
}
}
Any of the above would work, as would other synchronization mechanisms. As with all things, there are multiple ways you could solve the problem.
For additional reading,
the Concurrency lesson (in Java Tutorials) has good info
and might be worth your time.
In an application I'm working on I found the following code snippet:
public class MyClass {
private AtomicBoolean atomicBoolean = new AtomicBoolean(false);
public void Execute() {
// Whole lot of business logic
// ....
synchronized (this.atomicBoolean) {
// Want to make sure that execution is stopped if Stop() was called
if (this.atomicBoolean.get()) {
throw new SpecificException("...");
}
// Some more business logic...
}
}
public void Stop() {
synchronized (this.atomicBoolean) {
this.atomicBoolean.set(true);
}
}
}
According to FindBugs this is not correct as I can't use an AtomicBoolean together with synchronized and expect it to block the object.
My question is: What is the correct way to rewrite this methods? I've read about using an lock Object together with a boolean attribute instead but it appears kinda clumsy to introduce two new attributes for this lock.
Edit: As stated in a comment below: I think the intention is that in the two synchronized blocks, the AtomicBoolean can't be changed and that while one Thread is in one of the synchronized blocks, none other such block could be entered.
just replace the synchronized (this.atomicBoolean) { part from both methods, AtomicBoolean::get and AtomicBoolean::set is already atomic.
...I can't use an AtomicBoolean together with synchronized...
For whatever it's worth, the language allows you to synchronize on any object.
As a matter of style, some programmers prefer to only synchronize on a private object that is used for no other purpose.
private static Object foobarLock = new Object();
...
public void fooItUp(...) {
...
synchronized(foobarLock) {
...
}
...
}
...and expect it to block the object
Just to be clear, when some thread T enters a synchronized (o) {...} block, that does not prevent other threads from accessing or modifying the object o. The only thing it prevents is, it prevents some other thread U from entering a synchronized block on the same object o at the same time.
If I have something like below, so what does that mean inside synchronized block
synchronised (syncObject) {
Basically, it will means only one thread can be inside the above block and as soon as one thread is finished executing, second thread will enter that synchronized block synchronised (syncObject). Right?
Can anyone explain to me in a LayMan language so that I can get better picture?
private static final class Task implements Runnable {
{
private static Object syncObject = new Object();
public Task(Command command, BlockingQueue<Integer> pool1, BlockingQueue<Integer> pool2) {
this.command = command;
this.existPool = pool1;
this.newPool = pool2;
}
public void run()
{
synchronised (syncObject) {
if() {
existId = existPool.take();
attributeMethod(existId);
} else if() {
newId = newPool.take();
attributeMethod(newId);
}
}
}
}
// So I need to make this method synchronized or not? Currently I have made this synchronized
private synchronized void attributeMethod(int range) {
// And suppose If I am calling any other method here-
sampleMethod();
}
// What about this method, I need to make this synchronized as well? or not?
private synchronized void sampleMethod() {
}
Basically, it will means only one thread can be inside the above block and as soon as one thread is finished executing, second thread will enter that synchronized block synchronised (syncObject). Right?
Right!
So I need to make this method synchronized or not?
No you don't. Assuming that the method is only going to be called from within the synchronized block in the run() method, that block will already prevent multiple threads from executing the method simultaneously. So declaring the method to be synchronized is redundant.
However, I should point out some things:
When you declare an instance method as synchronized, it will synchronize on this; i.e. on the Task object. But your synchronized block is synchronizing on a different object ... the object in syncObject. In this case, this doesn't matter. However, if the synchronized block in the run() method wasn't there, you would find that the threads were attempting synchronizing on different objects ... and you would NOT get mutual exclusion.
By synchronizing at the top level of the run() method ... using a single shared syncObject for all threads that execute that task ... you are effectively making the tasks run one at a time. This completely negates any benefits of using threads.
It is good practice to declare the variable containing a private lock object (such as syncObject) to be final. This avoids the possibility that something might overwrite it ... resulting in a synchronization failure.
No, attributeMethod is already running within the scope of a synchronized block; no need to mark it as such, unless you intend to call it concurrently outside this block.
A warning is showing every time I synchronize on a non-final class field. Here is the code:
public class X
{
private Object o;
public void setO(Object o)
{
this.o = o;
}
public void x()
{
synchronized (o) // synchronization on a non-final field
{
}
}
}
so I changed the coding in the following way:
public class X
{
private final Object o;
public X()
{
o = new Object();
}
public void x()
{
synchronized (o)
{
}
}
}
I am not sure the above code is the proper way to synchronize on a non-final class field. How can I synchronize a non final field?
First of all, I encourage you to really try hard to deal with concurrency issues on a higher level of abstraction, i.e. solving it using classes from java.util.concurrent such as ExecutorServices, Callables, Futures etc.
That being said, there's nothing wrong with synchronizing on a non-final field per se. You just need to keep in mind that if the object reference changes, the same section of code may be run in parallel. I.e., if one thread runs the code in the synchronized block and someone calls setO(...), another thread can run the same synchronized block on the same instance concurrently.
Synchronize on the object which you need exclusive access to (or, better yet, an object dedicated to guarding it).
It's really not a good idea - because your synchronized blocks are no longer really synchronized in a consistent way.
Assuming the synchronized blocks are meant to be ensuring that only one thread accesses some shared data at a time, consider:
Thread 1 enters the synchronized block. Yay - it has exclusive access to the shared data...
Thread 2 calls setO()
Thread 3 (or still 2...) enters the synchronized block. Eek! It think it has exclusive access to the shared data, but thread 1 is still furtling with it...
Why would you want this to happen? Maybe there are some very specialized situations where it makes sense... but you'd have to present me with a specific use case (along with ways of mitigating the sort of scenario I've given above) before I'd be happy with it.
I agree with one of John's comment: You must always use a final lock dummy while accessing a non-final variable to prevent inconsistencies in case of the variable's reference changes. So in any cases and as a first rule of thumb:
Rule#1: If a field is non-final, always use a (private) final lock dummy.
Reason #1: You hold the lock and change the variable's reference by yourself. Another thread waiting outside the synchronized lock will be able to enter the guarded block.
Reason #2: You hold the lock and another thread changes the variable's reference. The result is the same: Another thread can enter the guarded block.
But when using a final lock dummy, there is another problem: You might get wrong data, because your non-final object will only be synchronized with RAM when calling synchronize(object). So, as a second rule of thumb:
Rule#2: When locking a non-final object you always need to do both: Using a final lock dummy and the lock of the non-final object for the sake of RAM synchronisation. (The only alternative will be declaring all fields of the object as volatile!)
These locks are also called "nested locks". Note that you must call them always in the same order, otherwise you will get a dead lock:
public class X {
private final LOCK;
private Object o;
public void setO(Object o){
this.o = o;
}
public void x() {
synchronized (LOCK) {
synchronized(o){
//do something with o...
}
}
}
}
As you can see I write the two locks directly on the same line, because they always belong together. Like this, you could even do 10 nesting locks:
synchronized (LOCK1) {
synchronized (LOCK2) {
synchronized (LOCK3) {
synchronized (LOCK4) {
//entering the locked space
}
}
}
}
Note that this code won't break if you just acquire an inner lock like synchronized (LOCK3) by another threads. But it will break if you call in another thread something like this:
synchronized (LOCK4) {
synchronized (LOCK1) { //dead lock!
synchronized (LOCK3) {
synchronized (LOCK2) {
//will never enter here...
}
}
}
}
There is only one workaround around such nested locks while handling non-final fields:
Rule #2 - Alternative: Declare all fields of the object as volatile. (I won't talk here about the disadvantages of doing this, e.g. preventing any storage in x-level caches even for reads, aso.)
So therefore aioobe is quite right: Just use java.util.concurrent. Or begin to understand everything about synchronisation and do it by yourself with nested locks. ;)
For more details why synchronisation on non-final fields breaks, have a look into my test case: https://stackoverflow.com/a/21460055/2012947
And for more details why you need synchronized at all due to RAM and caches have a look here: https://stackoverflow.com/a/21409975/2012947
I'm not really seeing the correct answer here, that is, It's perfectly alright to do it.
I'm not even sure why it's a warning, there is nothing wrong with it. The JVM makes sure that you get some valid object back (or null) when you read a value, and you can synchronize on any object.
If you plan on actually changing the lock while it's in use (as opposed to e.g. changing it from an init method, before you start using it), you have to make the variable that you plan to change volatile. Then all you need to do is to synchronize on both the old and the new object, and you can safely change the value
public volatile Object lock;
...
synchronized (lock) {
synchronized (newObject) {
lock = newObject;
}
}
There. It's not complicated, writing code with locks (mutexes) is actally quite easy. Writing code without them (lock free code) is what's hard.
EDIT: So this solution (as suggested by Jon Skeet) might have an issue with atomicity of implementation of "synchronized(object){}" while object reference is changing. I asked separately and according to Mr. erickson it is not thread safe - see: Is entering synchronized block atomic?. So take it as example how to NOT do it - with links why ;)
See the code how it would work if synchronised() would be atomic:
public class Main {
static class Config{
char a='0';
char b='0';
public void log(){
synchronized(this){
System.out.println(""+a+","+b);
}
}
}
static Config cfg = new Config();
static class Doer extends Thread {
char id;
Doer(char id) {
this.id = id;
}
public void mySleep(long ms){
try{Thread.sleep(ms);}catch(Exception ex){ex.printStackTrace();}
}
public void run() {
System.out.println("Doer "+id+" beg");
if(id == 'X'){
synchronized (cfg){
cfg.a=id;
mySleep(1000);
// do not forget to put synchronize(cfg) over setting new cfg - otherwise following will happend
// here it would be modifying different cfg (cos Y will change it).
// Another problem would be that new cfg would be in parallel modified by Z cos synchronized is applied on new object
cfg.b=id;
}
}
if(id == 'Y'){
mySleep(333);
synchronized(cfg) // comment this and you will see inconsistency in log - if you keep it I think all is ok
{
cfg = new Config(); // introduce new configuration
// be aware - don't expect here to be synchronized on new cfg!
// Z might already get a lock
}
}
if(id == 'Z'){
mySleep(666);
synchronized (cfg){
cfg.a=id;
mySleep(100);
cfg.b=id;
}
}
System.out.println("Doer "+id+" end");
cfg.log();
}
}
public static void main(String[] args) throws InterruptedException {
Doer X = new Doer('X');
Doer Y = new Doer('Y');
Doer Z = new Doer('Z');
X.start();
Y.start();
Z.start();
}
}
AtomicReference suits for your requirement.
From java documentation about atomic package:
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:
boolean compareAndSet(expectedValue, updateValue);
Sample code:
String initialReference = "value 1";
AtomicReference<String> someRef =
new AtomicReference<String>(initialReference);
String newReference = "value 2";
boolean exchanged = someRef.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
In above example, you replace String with your own Object
Related SE question:
When to use AtomicReference in Java?
If o never changes for the lifetime of an instance of X, the second version is better style irrespective of whether synchronization is involved.
Now, whether there's anything wrong with the first version is impossible to answer without knowing what else is going on in that class. I would tend to agree with the compiler that it does look error-prone (I won't repeat what the others have said).
Just adding my two cents: I had this warning when I used component that is instantiated through designer, so it's field cannot really be final, because constructor cannot takes parameters. In other words, I had quasi-final field without the final keyword.
I think that's why it is just warning: you are probably doing something wrong, but it might be right as well.
This is a problem I encounter frequently in working with more complex systems and which I have never figured out a good way to solve. It usually involves variations on the theme of a shared object whose construction and initialization are necessarily two distinct steps. This is generally because of architectural requirements, similar to applets, so answers that suggest I consolidate construction and initialization are not useful. The systems have to target Java 4 at the latest, so answers that suggest support available only in later JVMs are not useful either.
By way of example, let's say I have a class that is structured to fit into an application framework like so:
public class MyClass
{
private /*ideally-final*/ SomeObject someObject;
MyClass() {
someObject=null;
}
public void startup() {
someObject=new SomeObject(...arguments from environment which are not available until startup is called...);
}
public void shutdown() {
someObject=null; // this is not necessary, I am just expressing the intended scope of someObject explicitly
}
}
I can't make someObject final since it can't be set until startup() is invoked. But I would really like it to reflect its write-once semantics and be able to directly access it from multiple threads, preferably avoiding synchronization.
The idea being to express and enforce a degree of finalness, I conjecture that I could create a generic container, like so (UPDATE - corrected threading sematics of this class):
public class WormRef<T>
{
private volatile T reference; // wrapped reference
public WormRef() {
reference=null;
}
public WormRef<T> init(T val) {
if(reference!=null) { throw new IllegalStateException("The WormRef container is already initialized"); }
reference=val;
return this;
}
public T get() {
if(reference==null) { throw new IllegalStateException("The WormRef container is not initialized"); }
return reference;
}
}
and then in MyClass, above, do:
private final WormRef<SomeObject> someObject;
MyClass() {
someObject=new WormRef<SomeObject>();
}
public void startup() {
someObject.init(new SomeObject(...));
}
public void sometimeLater() {
someObject.get().doSomething();
}
Which raises some questions for me:
Is there a better way, or existing Java object (would have to be available in Java 4)?
Secondarily, in terms of thread safety:
Is this thread-safe provided that no other thread accesses someObject.get() until after its set() has been called. The other threads will only invoke methods on MyClass between startup() and shutdown() - the framework guarantees this.
Given the completely unsynchronized WormReference container, it is ever possible under either JMM to see a value of object which is neither null nor a reference to a SomeObject? In other words, does the JMM always guarantee that no thread can observe the memory of an object to be whatever values happened to be on the heap when the object was allocated. I believe the answer is "Yes" because allocation explicitly zeroes the allocated memory - but can CPU caching result in something else being observed at a given memory location?
Is it sufficient to make WormRef.reference volatile to ensure proper multithreaded semantics?
Note the primary thrust of this question is how to express and enforce the finalness of someObject without being able to actually mark it final; secondary is what is necessary for thread-safety. That is, don't get too hung up on the thread-safety aspect of this.
I would start by declaring your someObject volatile.
private volatile SomeObject someObject;
Volatile keyword creates a memory barrier, which means separate threads will always see updated memory when referencing someObject.
In your current implementation some threads may still see someObject as null even after startup has been called.
Actually this volatile technique is used a lot by collections declared in java.util.concurrent package.
And as some other posters suggest here, if all else fails fall back to full synchronization.
I would remove the setter method in WoRmObject, and provide a synchronised init() method which throws an exception if (object != null)
Consider using AtomicReference as a delegate in this object-container you're trying to create. For example:
public class Foo<Bar> {
private final AtomicReference<Bar> myBar = new AtomicReference<Bar>();
public Bar get() {
if (myBar.get()==null) myBar.compareAndSet(null,init());
return myBar.get();
}
Bar init() { /* ... */ }
//...
}
EDITED: That will set once, with some lazy-initialization method. It's not perfect for blocking multiple calls to a (presumably expensive) init(), but it could be worse. You could stick the instantiation of myBar into constructor, and then later add a constructor that allows assignment as well, if provided the correct info.
There's some general discussion of thread-safe, singleton instantiation (which is pretty similar to your problem) at, for example, this site.
In theory it would be sufficient to rewrite startup() as follows:
public synchronized void startup() {
if (someObject == null) someObject = new SomeObject();
}
By the way, although the WoRmObject is final, threads can still invoke set() multiple times. You'll really need to add some synchronization.
update: I played a bit round it and created an SSCCE, you may find it useful to play a bit around with it :)
package com.stackoverflow.q2428725;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String... args) throws Exception {
Bean bean = new Bean();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
executor.schedule(new StartupTask(bean), 2, TimeUnit.SECONDS);
executor.schedule(new StartupTask(bean), 2, TimeUnit.SECONDS);
Future<String> result1 = executor.submit(new GetTask(bean));
Future<String> result2 = executor.submit(new GetTask(bean));
System.out.println("Result1: " + result1.get());
System.out.println("Result2: " + result2.get());
executor.shutdown();
}
}
class Bean {
private String property;
private CountDownLatch latch = new CountDownLatch(1);
public synchronized void startup() {
if (property == null) {
System.out.println("Setting property.");
property = "foo";
latch.countDown();
} else {
System.out.println("Property already set!");
}
}
public String get() {
try {
latch.await();
} catch (InterruptedException e) {
// handle.
}
return property;
}
}
class StartupTask implements Runnable {
private Bean bean;
public StartupTask(Bean bean) {
this.bean = bean;
}
public void run() {
System.out.println("Starting up bean...");
bean.startup();
System.out.println("Bean started!");
}
}
class GetTask implements Callable<String> {
private Bean bean;
public GetTask(Bean bean) {
this.bean = bean;
}
public String call() {
System.out.println("Getting bean property...");
String property = bean.get();
System.out.println("Bean property got!");
return property;
}
}
The CountDownLatch will cause all await() calls to block until the countdown reaches zero.
It is most likely thread safe, from your description of the framework. There must have been a memory barrier somewhere between calling myobj.startup() and making myobj available to other threads. That guarantees that the writes in startup() will be visible to other threads. Therefore you don't have to worry about thread safety because the framework does it. There is no free lunch though; everytime another thread obtains access to myobj through the framework, it must involve sync or volatile read.
If you look into the framework and list the code in the path, you'll see sync/volatile in proper places that make your code thread safe. That is, if the framework is correctly implemented.
Let's examine a typical swing example, where a worker threads does some calculation, saves the results in a global variable x, then sends a repaint event. The GUI thread upon receiving the repaint event, reads the results from the global variable x, and repaints accordingly.
Neither the worker thread nor the repaint code does any synchronization or volatile read/write on anything. There must be tens of thousands of implementations like this. Luckily they are all thread safe even though the programmers paid no special attention. Why? Because the event queue is synchronized; we have a nice happends-before chain:
write x - insert event - read event - read x
Therefore write x and read x are properly synchronized, implicitly via event framework.
how about synchronization?
No it is not thread safe. Without synchronization, the new state of your variable might never get communicated to other threads.
Yes, as far as I know references are atomic so you will see either null or the reference. Note that the state of the referenced object is a completely different story
Could you use a ThreadLocal that only allows each thread's value to be set once?
There are a LOT of wrong ways to do lazy instantiation, especially in Java.
In short, the naive approach is to create a private object, a public synchronized init method, and a public unsynchronized get method that performs a null check on your object and calls init if necessary. The intricacies of the problem come in performing the null check in a thread safe way.
This article should be of use: http://en.wikipedia.org/wiki/Double-checked_locking
This specific topic, in Java, is discussed in depth in Doug Lea's 'Concurrent Programming in Java' which is somewhat out of date, and in 'Java Concurrency in Practice' coauthored by Lea and others. In particular, CPJ was published before the release of Java 5, which significantly improved Java's concurrency controls.
I can post more specifics when I get home and have access to said books.
This is my final answer, Regis1 :
/**
* Provides a simple write-one, read-many wrapper for an object reference for those situations
* where you have an instance variable which you would like to declare as final but can't because
* the instance initialization extends beyond construction.
* <p>
* An example would be <code>java.awt.Applet</code> with its constructor, <code>init()</code> and
* <code>start()</code> methods.
* <p>
* Threading Design : [ ] Single Threaded [x] Threadsafe [ ] Immutable [ ] Isolated
*
* #since Build 2010.0311.1923
*/
public class WormRef<T>
extends Object
{
private volatile T reference; // wrapped reference
public WormRef() {
super();
reference=null;
}
public WormRef<T> init(T val) {
// Use synchronization to prevent a race-condition whereby the following interation could happen between three threads
//
// Thread 1 Thread 2 Thread 3
// --------------- --------------- ---------------
// init-read null
// init-read null
// init-write A
// get A
// init-write B
// get B
//
// whereby Thread 3 sees A on the first get and B on subsequent gets.
synchronized(this) {
if(reference!=null) { throw new IllegalStateException("The WormRef container is already initialized"); }
reference=val;
}
return this;
}
public T get() {
if(reference==null) { throw new IllegalStateException("The WormRef container is not initialized"); }
return reference;
}
} // END PUBLIC CLASS
(1) Confer the game show "So you want to be a millionaire", hosted by Regis Philburn.
Just my little version based on AtomicReference. It's probably not the best, but I believe it to be clean and easy to use:
public static class ImmutableReference<V> {
private AtomicReference<V> ref = new AtomicReference<V>(null);
public boolean trySet(V v)
{
if(v == null)
throw new IllegalArgumentException("ImmutableReference cannot hold null values");
return ref.compareAndSet(null, v);
}
public void set(V v)
{
if(!trySet(v)) throw new IllegalStateException("Trying to modify an immutable reference");
}
public V get()
{
V v = ref.get();
if(v == null)
throw new IllegalStateException("Not initialized immutable reference.");
return v;
}
public V tryGet()
{
return ref.get();
}
}
First question: Why can't you just make start up a private method, called in the constructor, then it can be final. This would ensure thread safety after the constructor is called, as it is invisible before and only read after the constructor returns. Or re-factor your class structure so that the start-up method can create the MyClass object as part of its constructor. In may ways this particular case seems like a case of poor structure, where you really just want to make it final and immutable.
The easy Approach, if the class is immutable, and is read only after it is created, then wrap it in an Immutable List from guava. You can also make your own immutable wrapper which defensively copies when asked to return the reference, so this prevents a client from changing the reference. If it is immutable internally, then no further synchronization is needed, and unsynchronized reads are permissible. You can set your wrapper to defensively copy on request, so even attempts to write to it fail cleanly (they just don't do anything). You may need a memory barrier, or you may be able to do lazy initialisation, although note that lazy initialisation may require further synchronization, as you may get several unsynchronized read requests while the object is being constructed.
The slightly more involved approach would involve using an enumeration. Since enumerations are guaranteed singleton, then as soon as the enumeration is created it is fixed for ever. You still have to make sure that the object is internally immutable, but it does guarantee its singleton status. Without much effort.
The following class could answer your question. Some thread-safety achieved by using a volatile intermediate variable in conjunction with final value keeper in the provided generic. You may consider further increase of it by using synchronized setter/getter. Hope it helps.
https://stackoverflow.com/a/38290652/6519864