CDI PostConstruct and volatile fields
up vote
2
down vote
favorite
Using a post construct approach when we want to conditionally initialise some of the bean's fields, do we need to care about volatility of the field, since it is a multithread environment?
Say, we have something like this:
@ApplicationScoped
public class FooService
private final ConfigurationService configurationService;
private FooBean fooBean;
@Inject
FooService(ConfigurationService configurationService)
this.configurationService = configurationService;
void init(@Observes @Initialized(ApplicationScoped.class) Object ignored)
if (configurationService.isFooBeanInitialisationEnabled())
fooBean = initialiseFooBean(configurationService); // some initialisation
void cleanup(@Observes @Destroyed(ApplicationScoped.class) Object ignored)
if (fooBean != null)
fooBean.cleanup();
So should the fooBean
be wrapped into, let's say, the AtomicReference
or be a volatile
or it would be a redundant extra protection?
P.S. In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not? However I would like to have an answer for a more general case.
java java-ee concurrency cdi volatile
add a comment |
up vote
2
down vote
favorite
Using a post construct approach when we want to conditionally initialise some of the bean's fields, do we need to care about volatility of the field, since it is a multithread environment?
Say, we have something like this:
@ApplicationScoped
public class FooService
private final ConfigurationService configurationService;
private FooBean fooBean;
@Inject
FooService(ConfigurationService configurationService)
this.configurationService = configurationService;
void init(@Observes @Initialized(ApplicationScoped.class) Object ignored)
if (configurationService.isFooBeanInitialisationEnabled())
fooBean = initialiseFooBean(configurationService); // some initialisation
void cleanup(@Observes @Destroyed(ApplicationScoped.class) Object ignored)
if (fooBean != null)
fooBean.cleanup();
So should the fooBean
be wrapped into, let's say, the AtomicReference
or be a volatile
or it would be a redundant extra protection?
P.S. In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not? However I would like to have an answer for a more general case.
java java-ee concurrency cdi volatile
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
Using a post construct approach when we want to conditionally initialise some of the bean's fields, do we need to care about volatility of the field, since it is a multithread environment?
Say, we have something like this:
@ApplicationScoped
public class FooService
private final ConfigurationService configurationService;
private FooBean fooBean;
@Inject
FooService(ConfigurationService configurationService)
this.configurationService = configurationService;
void init(@Observes @Initialized(ApplicationScoped.class) Object ignored)
if (configurationService.isFooBeanInitialisationEnabled())
fooBean = initialiseFooBean(configurationService); // some initialisation
void cleanup(@Observes @Destroyed(ApplicationScoped.class) Object ignored)
if (fooBean != null)
fooBean.cleanup();
So should the fooBean
be wrapped into, let's say, the AtomicReference
or be a volatile
or it would be a redundant extra protection?
P.S. In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not? However I would like to have an answer for a more general case.
java java-ee concurrency cdi volatile
Using a post construct approach when we want to conditionally initialise some of the bean's fields, do we need to care about volatility of the field, since it is a multithread environment?
Say, we have something like this:
@ApplicationScoped
public class FooService
private final ConfigurationService configurationService;
private FooBean fooBean;
@Inject
FooService(ConfigurationService configurationService)
this.configurationService = configurationService;
void init(@Observes @Initialized(ApplicationScoped.class) Object ignored)
if (configurationService.isFooBeanInitialisationEnabled())
fooBean = initialiseFooBean(configurationService); // some initialisation
void cleanup(@Observes @Destroyed(ApplicationScoped.class) Object ignored)
if (fooBean != null)
fooBean.cleanup();
So should the fooBean
be wrapped into, let's say, the AtomicReference
or be a volatile
or it would be a redundant extra protection?
P.S. In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not? However I would like to have an answer for a more general case.
java java-ee concurrency cdi volatile
java java-ee concurrency cdi volatile
edited Nov 9 at 14:42
asked Nov 9 at 14:26
Andremoniy
21.6k672153
21.6k672153
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
up vote
2
down vote
accepted
I would say it depends which thread is actually initiating and destroying the contexts.
If you use regular events, they are synchronous (asynchronous events have been added in CDI 2.0 with ObservesAsync
, see
Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService ) so they are called in the same thread as the caller.
In general, I don't think the same thread is used (in application servers or standalone applications) so I would recommend using volatile
to ensure the right value is seen (basically the value constructed seen on destroy thread). However, it is not a use case happening so much to initiate and destroy your application in a concurrent way...
add a comment |
up vote
2
down vote
FooService
is a singleton which is shared between all managed beans in the application.
Annotation Type ApplicationScoped
private FooBean fooBean
is a state of the singleton object.
By default, CDI does not manage concurrency so it is the responsibility of a developer.
In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not?
CDI specification does not restrict containers to use the same thread for initialization and destruction of the application context. This behavior is implementation specific. In general case those threads will be different because initialization happens on the thread handling the first request to the application but destruction happens on the thread handling request from management console.
do you have by anychange the part of the specification speaking about thread management?
– Nicolas Henneaux
Nov 9 at 15:30
This post by Stephan Knitelius summarizes the situation with concurrency management in CDI specification and provides guidance on how to replicate EJB concurrency mechanisms with CDI interceptors.
– Illya Kysil
Nov 9 at 23:25
add a comment |
up vote
1
down vote
You may delegate concurrency management to EJB container - if your runtime environment includes one.
Neither volatile
nor AtomicReference
are needed in this case!
Following definition will do the job:
@javax.ejb.Startup // initialize on application start
@javax.ejb.Singleton // EJB Singleton
public class FooService
private final ConfigurationService configurationService;
private FooBean fooBean;
@javax.inject.Inject
FooService(ConfigurationService configurationService)
this.configurationService = configurationService;
@javax.annotation.PostConstruct
void init()
if (configurationService.isFooBeanInitialisationEnabled())
fooBean = initialiseFooBean(configurationService); // some initialisation
@javax.annotation.PreDestroy
void cleanup()
if (fooBean != null)
fooBean.cleanup();
add a comment |
up vote
1
down vote
According to the specification:
An event with qualifier @Initialized(ApplicationScoped.class) is synchronously fired when the application context is initialized.
An event with qualifier @BeforeDestroyed(ApplicationScoped.class) is synchronously fired when the application context is about to be destroyed, i.e. before the actual destruction.
An event with qualifier @Destroyed(ApplicationScoped.class) is synchronously fired when the application context is destroyed, i.e. after the actual destruction.
And according to this presentation Bean manager lifecycle: the lifecycle of the bean manager is synchronous between the different states of the process and the sequence is kept: "destroy not before init".
Jboss are the specification lead of CDI 2.0
I do not see any scenario that would require a volatile/protection. Even if T1 inits then T2 destroys, it will be T1 then T2, not T1 and T2 concurrently.
And even if it would be concurrently, to have an issue it would imply weird scenario, edge scenario outside the CDI runtime:
- T2 calls
destroy
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: destroy before init, at this point we are in the 4th dimension of CDI), - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
Or
- T2 calls a method that access
fooBean
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: T1 is initialized whereasfooBean
has already been used by T2, at this point we are in the 4th dimension of CDI - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
1
thanks for the specification! However for cached value it doesn't need to be accessed to put in L* CPU cache. it doesn't even need to be concurrent calls.volatile
provides the guarantees that the CPU caches does contain the latest value written by any thread. In case of concurrency betweeninit
anddestroy
it could happen that you getnull
value.
– Nicolas Henneaux
Nov 12 at 13:57
it could happen that you get null value
How and when? Cache is coherent and volatile on x86 is mostly about not caching into register not CPU cache
– Nicolas Labrot
Nov 12 at 14:19
First, imagineinit
anddestroy
execute at the same time anddestroy
reaches first the fieldfooBean
, it would seenull
with or withoutvolatile
. Another situation whenvolatile
could help, if one thread executesinit
whilefooBean
is cached on all L1 caches, it changes only value in the value in its core while the other cores still holdnull
in their L1 caches. Ifdestroy
executes after without other operation on the cache it could seenull
without any violation in the Java specification.
– Nicolas Henneaux
Nov 12 at 15:34
1
init and destroy execute at the same time
: do we agree that this scenario is not possible?is cached on all L1 caches, it changes only value in the value in its core while the other cores still hold null in their L1 caches.
: the cache coherence mechanism will ensure that in other L1 cache, the entries are invalidated. So if destroy executes after, it will not seenull
– Nicolas Labrot
Nov 12 at 16:07
add a comment |
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
I would say it depends which thread is actually initiating and destroying the contexts.
If you use regular events, they are synchronous (asynchronous events have been added in CDI 2.0 with ObservesAsync
, see
Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService ) so they are called in the same thread as the caller.
In general, I don't think the same thread is used (in application servers or standalone applications) so I would recommend using volatile
to ensure the right value is seen (basically the value constructed seen on destroy thread). However, it is not a use case happening so much to initiate and destroy your application in a concurrent way...
add a comment |
up vote
2
down vote
accepted
I would say it depends which thread is actually initiating and destroying the contexts.
If you use regular events, they are synchronous (asynchronous events have been added in CDI 2.0 with ObservesAsync
, see
Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService ) so they are called in the same thread as the caller.
In general, I don't think the same thread is used (in application servers or standalone applications) so I would recommend using volatile
to ensure the right value is seen (basically the value constructed seen on destroy thread). However, it is not a use case happening so much to initiate and destroy your application in a concurrent way...
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
I would say it depends which thread is actually initiating and destroying the contexts.
If you use regular events, they are synchronous (asynchronous events have been added in CDI 2.0 with ObservesAsync
, see
Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService ) so they are called in the same thread as the caller.
In general, I don't think the same thread is used (in application servers or standalone applications) so I would recommend using volatile
to ensure the right value is seen (basically the value constructed seen on destroy thread). However, it is not a use case happening so much to initiate and destroy your application in a concurrent way...
I would say it depends which thread is actually initiating and destroying the contexts.
If you use regular events, they are synchronous (asynchronous events have been added in CDI 2.0 with ObservesAsync
, see
Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService ) so they are called in the same thread as the caller.
In general, I don't think the same thread is used (in application servers or standalone applications) so I would recommend using volatile
to ensure the right value is seen (basically the value constructed seen on destroy thread). However, it is not a use case happening so much to initiate and destroy your application in a concurrent way...
answered Nov 9 at 14:53
Nicolas Henneaux
5,13442647
5,13442647
add a comment |
add a comment |
up vote
2
down vote
FooService
is a singleton which is shared between all managed beans in the application.
Annotation Type ApplicationScoped
private FooBean fooBean
is a state of the singleton object.
By default, CDI does not manage concurrency so it is the responsibility of a developer.
In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not?
CDI specification does not restrict containers to use the same thread for initialization and destruction of the application context. This behavior is implementation specific. In general case those threads will be different because initialization happens on the thread handling the first request to the application but destruction happens on the thread handling request from management console.
do you have by anychange the part of the specification speaking about thread management?
– Nicolas Henneaux
Nov 9 at 15:30
This post by Stephan Knitelius summarizes the situation with concurrency management in CDI specification and provides guidance on how to replicate EJB concurrency mechanisms with CDI interceptors.
– Illya Kysil
Nov 9 at 23:25
add a comment |
up vote
2
down vote
FooService
is a singleton which is shared between all managed beans in the application.
Annotation Type ApplicationScoped
private FooBean fooBean
is a state of the singleton object.
By default, CDI does not manage concurrency so it is the responsibility of a developer.
In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not?
CDI specification does not restrict containers to use the same thread for initialization and destruction of the application context. This behavior is implementation specific. In general case those threads will be different because initialization happens on the thread handling the first request to the application but destruction happens on the thread handling request from management console.
do you have by anychange the part of the specification speaking about thread management?
– Nicolas Henneaux
Nov 9 at 15:30
This post by Stephan Knitelius summarizes the situation with concurrency management in CDI specification and provides guidance on how to replicate EJB concurrency mechanisms with CDI interceptors.
– Illya Kysil
Nov 9 at 23:25
add a comment |
up vote
2
down vote
up vote
2
down vote
FooService
is a singleton which is shared between all managed beans in the application.
Annotation Type ApplicationScoped
private FooBean fooBean
is a state of the singleton object.
By default, CDI does not manage concurrency so it is the responsibility of a developer.
In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not?
CDI specification does not restrict containers to use the same thread for initialization and destruction of the application context. This behavior is implementation specific. In general case those threads will be different because initialization happens on the thread handling the first request to the application but destruction happens on the thread handling request from management console.
FooService
is a singleton which is shared between all managed beans in the application.
Annotation Type ApplicationScoped
private FooBean fooBean
is a state of the singleton object.
By default, CDI does not manage concurrency so it is the responsibility of a developer.
In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not?
CDI specification does not restrict containers to use the same thread for initialization and destruction of the application context. This behavior is implementation specific. In general case those threads will be different because initialization happens on the thread handling the first request to the application but destruction happens on the thread handling request from management console.
answered Nov 9 at 15:21
Illya Kysil
48425
48425
do you have by anychange the part of the specification speaking about thread management?
– Nicolas Henneaux
Nov 9 at 15:30
This post by Stephan Knitelius summarizes the situation with concurrency management in CDI specification and provides guidance on how to replicate EJB concurrency mechanisms with CDI interceptors.
– Illya Kysil
Nov 9 at 23:25
add a comment |
do you have by anychange the part of the specification speaking about thread management?
– Nicolas Henneaux
Nov 9 at 15:30
This post by Stephan Knitelius summarizes the situation with concurrency management in CDI specification and provides guidance on how to replicate EJB concurrency mechanisms with CDI interceptors.
– Illya Kysil
Nov 9 at 23:25
do you have by anychange the part of the specification speaking about thread management?
– Nicolas Henneaux
Nov 9 at 15:30
do you have by anychange the part of the specification speaking about thread management?
– Nicolas Henneaux
Nov 9 at 15:30
This post by Stephan Knitelius summarizes the situation with concurrency management in CDI specification and provides guidance on how to replicate EJB concurrency mechanisms with CDI interceptors.
– Illya Kysil
Nov 9 at 23:25
This post by Stephan Knitelius summarizes the situation with concurrency management in CDI specification and provides guidance on how to replicate EJB concurrency mechanisms with CDI interceptors.
– Illya Kysil
Nov 9 at 23:25
add a comment |
up vote
1
down vote
You may delegate concurrency management to EJB container - if your runtime environment includes one.
Neither volatile
nor AtomicReference
are needed in this case!
Following definition will do the job:
@javax.ejb.Startup // initialize on application start
@javax.ejb.Singleton // EJB Singleton
public class FooService
private final ConfigurationService configurationService;
private FooBean fooBean;
@javax.inject.Inject
FooService(ConfigurationService configurationService)
this.configurationService = configurationService;
@javax.annotation.PostConstruct
void init()
if (configurationService.isFooBeanInitialisationEnabled())
fooBean = initialiseFooBean(configurationService); // some initialisation
@javax.annotation.PreDestroy
void cleanup()
if (fooBean != null)
fooBean.cleanup();
add a comment |
up vote
1
down vote
You may delegate concurrency management to EJB container - if your runtime environment includes one.
Neither volatile
nor AtomicReference
are needed in this case!
Following definition will do the job:
@javax.ejb.Startup // initialize on application start
@javax.ejb.Singleton // EJB Singleton
public class FooService
private final ConfigurationService configurationService;
private FooBean fooBean;
@javax.inject.Inject
FooService(ConfigurationService configurationService)
this.configurationService = configurationService;
@javax.annotation.PostConstruct
void init()
if (configurationService.isFooBeanInitialisationEnabled())
fooBean = initialiseFooBean(configurationService); // some initialisation
@javax.annotation.PreDestroy
void cleanup()
if (fooBean != null)
fooBean.cleanup();
add a comment |
up vote
1
down vote
up vote
1
down vote
You may delegate concurrency management to EJB container - if your runtime environment includes one.
Neither volatile
nor AtomicReference
are needed in this case!
Following definition will do the job:
@javax.ejb.Startup // initialize on application start
@javax.ejb.Singleton // EJB Singleton
public class FooService
private final ConfigurationService configurationService;
private FooBean fooBean;
@javax.inject.Inject
FooService(ConfigurationService configurationService)
this.configurationService = configurationService;
@javax.annotation.PostConstruct
void init()
if (configurationService.isFooBeanInitialisationEnabled())
fooBean = initialiseFooBean(configurationService); // some initialisation
@javax.annotation.PreDestroy
void cleanup()
if (fooBean != null)
fooBean.cleanup();
You may delegate concurrency management to EJB container - if your runtime environment includes one.
Neither volatile
nor AtomicReference
are needed in this case!
Following definition will do the job:
@javax.ejb.Startup // initialize on application start
@javax.ejb.Singleton // EJB Singleton
public class FooService
private final ConfigurationService configurationService;
private FooBean fooBean;
@javax.inject.Inject
FooService(ConfigurationService configurationService)
this.configurationService = configurationService;
@javax.annotation.PostConstruct
void init()
if (configurationService.isFooBeanInitialisationEnabled())
fooBean = initialiseFooBean(configurationService); // some initialisation
@javax.annotation.PreDestroy
void cleanup()
if (fooBean != null)
fooBean.cleanup();
answered Nov 9 at 23:37
Illya Kysil
48425
48425
add a comment |
add a comment |
up vote
1
down vote
According to the specification:
An event with qualifier @Initialized(ApplicationScoped.class) is synchronously fired when the application context is initialized.
An event with qualifier @BeforeDestroyed(ApplicationScoped.class) is synchronously fired when the application context is about to be destroyed, i.e. before the actual destruction.
An event with qualifier @Destroyed(ApplicationScoped.class) is synchronously fired when the application context is destroyed, i.e. after the actual destruction.
And according to this presentation Bean manager lifecycle: the lifecycle of the bean manager is synchronous between the different states of the process and the sequence is kept: "destroy not before init".
Jboss are the specification lead of CDI 2.0
I do not see any scenario that would require a volatile/protection. Even if T1 inits then T2 destroys, it will be T1 then T2, not T1 and T2 concurrently.
And even if it would be concurrently, to have an issue it would imply weird scenario, edge scenario outside the CDI runtime:
- T2 calls
destroy
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: destroy before init, at this point we are in the 4th dimension of CDI), - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
Or
- T2 calls a method that access
fooBean
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: T1 is initialized whereasfooBean
has already been used by T2, at this point we are in the 4th dimension of CDI - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
1
thanks for the specification! However for cached value it doesn't need to be accessed to put in L* CPU cache. it doesn't even need to be concurrent calls.volatile
provides the guarantees that the CPU caches does contain the latest value written by any thread. In case of concurrency betweeninit
anddestroy
it could happen that you getnull
value.
– Nicolas Henneaux
Nov 12 at 13:57
it could happen that you get null value
How and when? Cache is coherent and volatile on x86 is mostly about not caching into register not CPU cache
– Nicolas Labrot
Nov 12 at 14:19
First, imagineinit
anddestroy
execute at the same time anddestroy
reaches first the fieldfooBean
, it would seenull
with or withoutvolatile
. Another situation whenvolatile
could help, if one thread executesinit
whilefooBean
is cached on all L1 caches, it changes only value in the value in its core while the other cores still holdnull
in their L1 caches. Ifdestroy
executes after without other operation on the cache it could seenull
without any violation in the Java specification.
– Nicolas Henneaux
Nov 12 at 15:34
1
init and destroy execute at the same time
: do we agree that this scenario is not possible?is cached on all L1 caches, it changes only value in the value in its core while the other cores still hold null in their L1 caches.
: the cache coherence mechanism will ensure that in other L1 cache, the entries are invalidated. So if destroy executes after, it will not seenull
– Nicolas Labrot
Nov 12 at 16:07
add a comment |
up vote
1
down vote
According to the specification:
An event with qualifier @Initialized(ApplicationScoped.class) is synchronously fired when the application context is initialized.
An event with qualifier @BeforeDestroyed(ApplicationScoped.class) is synchronously fired when the application context is about to be destroyed, i.e. before the actual destruction.
An event with qualifier @Destroyed(ApplicationScoped.class) is synchronously fired when the application context is destroyed, i.e. after the actual destruction.
And according to this presentation Bean manager lifecycle: the lifecycle of the bean manager is synchronous between the different states of the process and the sequence is kept: "destroy not before init".
Jboss are the specification lead of CDI 2.0
I do not see any scenario that would require a volatile/protection. Even if T1 inits then T2 destroys, it will be T1 then T2, not T1 and T2 concurrently.
And even if it would be concurrently, to have an issue it would imply weird scenario, edge scenario outside the CDI runtime:
- T2 calls
destroy
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: destroy before init, at this point we are in the 4th dimension of CDI), - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
Or
- T2 calls a method that access
fooBean
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: T1 is initialized whereasfooBean
has already been used by T2, at this point we are in the 4th dimension of CDI - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
1
thanks for the specification! However for cached value it doesn't need to be accessed to put in L* CPU cache. it doesn't even need to be concurrent calls.volatile
provides the guarantees that the CPU caches does contain the latest value written by any thread. In case of concurrency betweeninit
anddestroy
it could happen that you getnull
value.
– Nicolas Henneaux
Nov 12 at 13:57
it could happen that you get null value
How and when? Cache is coherent and volatile on x86 is mostly about not caching into register not CPU cache
– Nicolas Labrot
Nov 12 at 14:19
First, imagineinit
anddestroy
execute at the same time anddestroy
reaches first the fieldfooBean
, it would seenull
with or withoutvolatile
. Another situation whenvolatile
could help, if one thread executesinit
whilefooBean
is cached on all L1 caches, it changes only value in the value in its core while the other cores still holdnull
in their L1 caches. Ifdestroy
executes after without other operation on the cache it could seenull
without any violation in the Java specification.
– Nicolas Henneaux
Nov 12 at 15:34
1
init and destroy execute at the same time
: do we agree that this scenario is not possible?is cached on all L1 caches, it changes only value in the value in its core while the other cores still hold null in their L1 caches.
: the cache coherence mechanism will ensure that in other L1 cache, the entries are invalidated. So if destroy executes after, it will not seenull
– Nicolas Labrot
Nov 12 at 16:07
add a comment |
up vote
1
down vote
up vote
1
down vote
According to the specification:
An event with qualifier @Initialized(ApplicationScoped.class) is synchronously fired when the application context is initialized.
An event with qualifier @BeforeDestroyed(ApplicationScoped.class) is synchronously fired when the application context is about to be destroyed, i.e. before the actual destruction.
An event with qualifier @Destroyed(ApplicationScoped.class) is synchronously fired when the application context is destroyed, i.e. after the actual destruction.
And according to this presentation Bean manager lifecycle: the lifecycle of the bean manager is synchronous between the different states of the process and the sequence is kept: "destroy not before init".
Jboss are the specification lead of CDI 2.0
I do not see any scenario that would require a volatile/protection. Even if T1 inits then T2 destroys, it will be T1 then T2, not T1 and T2 concurrently.
And even if it would be concurrently, to have an issue it would imply weird scenario, edge scenario outside the CDI runtime:
- T2 calls
destroy
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: destroy before init, at this point we are in the 4th dimension of CDI), - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
Or
- T2 calls a method that access
fooBean
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: T1 is initialized whereasfooBean
has already been used by T2, at this point we are in the 4th dimension of CDI - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
According to the specification:
An event with qualifier @Initialized(ApplicationScoped.class) is synchronously fired when the application context is initialized.
An event with qualifier @BeforeDestroyed(ApplicationScoped.class) is synchronously fired when the application context is about to be destroyed, i.e. before the actual destruction.
An event with qualifier @Destroyed(ApplicationScoped.class) is synchronously fired when the application context is destroyed, i.e. after the actual destruction.
And according to this presentation Bean manager lifecycle: the lifecycle of the bean manager is synchronous between the different states of the process and the sequence is kept: "destroy not before init".
Jboss are the specification lead of CDI 2.0
I do not see any scenario that would require a volatile/protection. Even if T1 inits then T2 destroys, it will be T1 then T2, not T1 and T2 concurrently.
And even if it would be concurrently, to have an issue it would imply weird scenario, edge scenario outside the CDI runtime:
- T2 calls
destroy
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: destroy before init, at this point we are in the 4th dimension of CDI), - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
Or
- T2 calls a method that access
fooBean
(fooBean
is null and now 'cached' in a register) - Then T1 calls
init
: T1 is initialized whereasfooBean
has already been used by T2, at this point we are in the 4th dimension of CDI - Then T2 calls
destroy
(fooBean
is already cached in a register so is value is null)).
edited Nov 12 at 14:11
answered Nov 12 at 13:00
Nicolas Labrot
2,8221728
2,8221728
1
thanks for the specification! However for cached value it doesn't need to be accessed to put in L* CPU cache. it doesn't even need to be concurrent calls.volatile
provides the guarantees that the CPU caches does contain the latest value written by any thread. In case of concurrency betweeninit
anddestroy
it could happen that you getnull
value.
– Nicolas Henneaux
Nov 12 at 13:57
it could happen that you get null value
How and when? Cache is coherent and volatile on x86 is mostly about not caching into register not CPU cache
– Nicolas Labrot
Nov 12 at 14:19
First, imagineinit
anddestroy
execute at the same time anddestroy
reaches first the fieldfooBean
, it would seenull
with or withoutvolatile
. Another situation whenvolatile
could help, if one thread executesinit
whilefooBean
is cached on all L1 caches, it changes only value in the value in its core while the other cores still holdnull
in their L1 caches. Ifdestroy
executes after without other operation on the cache it could seenull
without any violation in the Java specification.
– Nicolas Henneaux
Nov 12 at 15:34
1
init and destroy execute at the same time
: do we agree that this scenario is not possible?is cached on all L1 caches, it changes only value in the value in its core while the other cores still hold null in their L1 caches.
: the cache coherence mechanism will ensure that in other L1 cache, the entries are invalidated. So if destroy executes after, it will not seenull
– Nicolas Labrot
Nov 12 at 16:07
add a comment |
1
thanks for the specification! However for cached value it doesn't need to be accessed to put in L* CPU cache. it doesn't even need to be concurrent calls.volatile
provides the guarantees that the CPU caches does contain the latest value written by any thread. In case of concurrency betweeninit
anddestroy
it could happen that you getnull
value.
– Nicolas Henneaux
Nov 12 at 13:57
it could happen that you get null value
How and when? Cache is coherent and volatile on x86 is mostly about not caching into register not CPU cache
– Nicolas Labrot
Nov 12 at 14:19
First, imagineinit
anddestroy
execute at the same time anddestroy
reaches first the fieldfooBean
, it would seenull
with or withoutvolatile
. Another situation whenvolatile
could help, if one thread executesinit
whilefooBean
is cached on all L1 caches, it changes only value in the value in its core while the other cores still holdnull
in their L1 caches. Ifdestroy
executes after without other operation on the cache it could seenull
without any violation in the Java specification.
– Nicolas Henneaux
Nov 12 at 15:34
1
init and destroy execute at the same time
: do we agree that this scenario is not possible?is cached on all L1 caches, it changes only value in the value in its core while the other cores still hold null in their L1 caches.
: the cache coherence mechanism will ensure that in other L1 cache, the entries are invalidated. So if destroy executes after, it will not seenull
– Nicolas Labrot
Nov 12 at 16:07
1
1
thanks for the specification! However for cached value it doesn't need to be accessed to put in L* CPU cache. it doesn't even need to be concurrent calls.
volatile
provides the guarantees that the CPU caches does contain the latest value written by any thread. In case of concurrency between init
and destroy
it could happen that you get null
value.– Nicolas Henneaux
Nov 12 at 13:57
thanks for the specification! However for cached value it doesn't need to be accessed to put in L* CPU cache. it doesn't even need to be concurrent calls.
volatile
provides the guarantees that the CPU caches does contain the latest value written by any thread. In case of concurrency between init
and destroy
it could happen that you get null
value.– Nicolas Henneaux
Nov 12 at 13:57
it could happen that you get null value
How and when? Cache is coherent and volatile on x86 is mostly about not caching into register not CPU cache– Nicolas Labrot
Nov 12 at 14:19
it could happen that you get null value
How and when? Cache is coherent and volatile on x86 is mostly about not caching into register not CPU cache– Nicolas Labrot
Nov 12 at 14:19
First, imagine
init
and destroy
execute at the same time and destroy
reaches first the field fooBean
, it would see null
with or without volatile
. Another situation when volatile
could help, if one thread executes init
while fooBean
is cached on all L1 caches, it changes only value in the value in its core while the other cores still hold null
in their L1 caches. If destroy
executes after without other operation on the cache it could see null
without any violation in the Java specification.– Nicolas Henneaux
Nov 12 at 15:34
First, imagine
init
and destroy
execute at the same time and destroy
reaches first the field fooBean
, it would see null
with or without volatile
. Another situation when volatile
could help, if one thread executes init
while fooBean
is cached on all L1 caches, it changes only value in the value in its core while the other cores still hold null
in their L1 caches. If destroy
executes after without other operation on the cache it could see null
without any violation in the Java specification.– Nicolas Henneaux
Nov 12 at 15:34
1
1
init and destroy execute at the same time
: do we agree that this scenario is not possible? is cached on all L1 caches, it changes only value in the value in its core while the other cores still hold null in their L1 caches.
: the cache coherence mechanism will ensure that in other L1 cache, the entries are invalidated. So if destroy executes after, it will not see null
– Nicolas Labrot
Nov 12 at 16:07
init and destroy execute at the same time
: do we agree that this scenario is not possible? is cached on all L1 caches, it changes only value in the value in its core while the other cores still hold null in their L1 caches.
: the cache coherence mechanism will ensure that in other L1 cache, the entries are invalidated. So if destroy executes after, it will not see null
– Nicolas Labrot
Nov 12 at 16:07
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53227585%2fcdi-postconstruct-and-volatile-fields%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown