You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Bojan Smojver <bo...@binarix.com> on 2001/10/01 10:24:07 UTC

Thread safety

Are Template.merge() and VelocityEngine.getTemplate() thread safe?

Bojan

Re: Thread safety

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
Man, look what the cat dragged in :)

On 10/1/01 5:23 PM, "Brian Goetz" <br...@quiotix.com> wrote:

> 
>>> merge() is as long as you don't share a VelocityContext across
>>> simultaneous threads.
>> 
>> Which means the answer is "no" ;)
> 
> Actually, I would say that this characterization is true but
> misleading.  The VelocityContext operations are explicitly not thread-safe,
> but merge() and friends are (according to Geir, I've not checked)
> thread-safe except to the extent that they use the VC.  While according to
> a dictionary definition, you might characterize this as being not
> thread-safe, in reality, as long as you are using VC properly (not sharing
> it across threads), then merge() and friends do not require additional
> synchronization.
> 

And again, it should only be with the VelocityContext class specifically.
This was done for convenience and efficiency for the most common usage.

Geir

>>  b) Pool VelocityContexts and recycle them. Since they already implement
>> clone() very nicely, this should be easy.
> 
> This is what WM does.  The Broker creates a Context at startup, and
> populates a pool using clone().  Alternately, you could use ThreadLocal to
> keep one around for each thread.

-- 
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
"They that can give up essential liberty to obtain a little temporary safety
deserve neither liberty nor safety." - Benjamin Franklin



Re: Thread safety

Posted by Brian Goetz <br...@quiotix.com>.
> > merge() is as long as you don't share a VelocityContext across
> > simultaneous threads.
>
>Which means the answer is "no" ;)

Actually, I would say that this characterization is true but 
misleading.  The VelocityContext operations are explicitly not thread-safe, 
but merge() and friends are (according to Geir, I've not checked) 
thread-safe except to the extent that they use the VC.  While according to 
a dictionary definition, you might characterize this as being not 
thread-safe, in reality, as long as you are using VC properly (not sharing 
it across threads), then merge() and friends do not require additional 
synchronization.

>  b) Pool VelocityContexts and recycle them. Since they already implement
>clone() very nicely, this should be easy.

This is what WM does.  The Broker creates a Context at startup, and 
populates a pool using clone().  Alternately, you could use ThreadLocal to 
keep one around for each thread.



--
Brian Goetz
Quiotix Corporation
brian@quiotix.com           Tel: 650-843-1300            Fax: 650-324-8032

http://www.quiotix.com


RE: Thread safety

Posted by Brian Goetz <br...@quiotix.com>.
>Well, what i'm actually referring to is creating a my defaultContext inside
>of my Servlet init() method. Which, i believe (but wouldn't swear to without
>reading the spec), is guaranteed to execute before any of attempt to "use"
>the context via the doPost/doGet  ... The objects I stick in there are, as
>you suggest, immutable ... examples include:
>
>- list of states
>- list of countries
>- "tool" objects that contain formatting functions (static methods) ...

It depends what hat you're wearing.  With my "Professor of Computer 
Science" hat (which I don't own, but borrow from friends when they're not 
looking), this is probably not guaranteed to be thread safe, as it is 
possible for the servlet container to have created multiple threads for 
running servlet requests, and have the init() execute in one and then the 
servlet used by the other.  On the other hand, putting my "Real World 
Programmer" hat on (mine, and well used) I would expect that there's enough 
other synchronization going on in the servlet container that this will 
probably not cause problems.

>so it sounds like, in my particular case, sharing a velocity context across
>threads is safe ..

Sharing the default context is, but sharing the per-request context will 
NOT be, unless you're either externally synchronizing, or not ever putting 
anything in the per-request context.



--
Brian Goetz
Quiotix Corporation
brian@quiotix.com           Tel: 650-843-1300            Fax: 650-324-8032

http://www.quiotix.com


Re: Thread safety

Posted by Bojan Smojver <bo...@binarix.com>.
Will Glass-Husain wrote:
> 
> Hi,
> 
> Just downloaded Velocity 1.2rc1.  Look forward to installing.
> 
> This is a basic question-- but what's the difference between a rc version
> and a regular version?  (Maybe there's a FAQ I should be checking on open
> source development?)

I think RC would stand for Release Candidate or something similar here.

Bojan

RE: Removal from list

Posted by Huy Do <hu...@tramada.com>.
why would you want to do that :-)
This is a great list, with heaps of great OT discussions  

> -----Original Message-----
> From: Allan Tomkinson [mailto:atomkinson@triad.rr.com]
> Sent: Tuesday, 2 October 2001 11:38 AM
> To: velocity-user@jakarta.apache.org
> Subject: Removal from list
> 
> 
> I was hoping someone could remove me from this list?  I tried the options
> that the mailing list website gave, but none of them worked.
> 
> Thanks,
> Allan
> 
> 

Removal from list

Posted by Allan Tomkinson <at...@triad.rr.com>.
I was hoping someone could remove me from this list?  I tried the options
that the mailing list website gave, but none of them worked.

Thanks,
Allan


Re: release candidate

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 10/1/01 8:55 PM, "Will Glass-Husain" <wg...@forio.com> wrote:

> Hi,
> 
> Just downloaded Velocity 1.2rc1.  Look forward to installing.
> 
> This is a basic question-- but what's the difference between a rc version
> and a regular version?  (Maybe there's a FAQ I should be checking on open
> source development?)

The 'release candidate' represents what we think the released version is
going to be - but still gives us wiggle room for any last minute fixes.

The hope is that as 1.2rc1, people will give it a fair shake w/o fear of it
being unstable or unready.

geir

> 
> Thanks, WILL
> 
> P.S.  Apologies for the repost-- please reply to this thread.
> 
> 

-- 
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
"They that can give up essential liberty to obtain a little temporary safety
deserve neither liberty nor safety." - Benjamin Franklin



release candidate

Posted by Will Glass-Husain <wg...@forio.com>.
Hi,

Just downloaded Velocity 1.2rc1.  Look forward to installing.

This is a basic question-- but what's the difference between a rc version
and a regular version?  (Maybe there's a FAQ I should be checking on open
source development?)

Thanks, WILL

P.S.  Apologies for the repost-- please reply to this thread.



RE: Thread safety

Posted by Will Glass-Husain <wg...@forio.com>.
Hi,

Just downloaded Velocity 1.2rc1.  Look forward to installing.

This is a basic question-- but what's the difference between a rc version
and a regular version?  (Maybe there's a FAQ I should be checking on open
source development?)

Thanks, WILL

-----Original Message-----
From: Geir Magnusson Jr. [mailto:geirm@optonline.net]
Sent: Monday, October 01, 2001 3:48 PM
To: velocity-user@jakarta.apache.org
Subject: Re: Thread safety


On 10/1/01 5:29 PM, "Brian Goetz" <br...@quiotix.com> wrote:

>
>> Is there something fancy that goes on with the Context during the merge()
>> that would make it non-thread-safe? Or is it just concern over the fact
that
>> #set() operations will change the content of the Context? (which isn't
>> thread safe)
>
> The Context is stateful, and its state is presumably stored in an
> unsynchronized map.  The cost of making it thread-safe doesn't seem to be
> worth it for the 0.01% of users who will be sharing the context across
> threads.  For them, its easy enough to synchronize all operations that
> would affect the Context.

Exactly.  And that's 'VelocityContext'.

>
>> I haven't stress tested the hell out of it but I have a "default" context
>> (with a bunch of global variables, tools, etc...) that I nest inside of
the
>> context that is created during each request ...
>>
>> VelocityContext ctx = new VelocityContext(defaultContext);
>>
>> is that safe?
>
> A more complicated question.  Without looking at the code (look ma, no
> hands), I'd say this operation is technically only safe if the following
> conditions are met:
> - the default context is constructed before other threads that use it are
> created,
> - nothing is ever added to or removed from the default context after it
> is initially created and populated,
> - the objects that the default context references are similarly immutable.
>
> (In reality, the first condition is probably not met, but there is almost
> certainly other synchronization that makes it work anyway, even though
> technically there could be race conditions on some architectures that
would
> make it not thread-safe.)

#2 and #3 are probably not required, but I just got home and haven't given
it deep thought.


geir

--
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
"Whoever would overthrow the liberty of a nation must begin by subduing the
freeness of speech." - Benjamin Franklin



Re: Thread safety

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 10/1/01 5:29 PM, "Brian Goetz" <br...@quiotix.com> wrote:

> 
>> Is there something fancy that goes on with the Context during the merge()
>> that would make it non-thread-safe? Or is it just concern over the fact that
>> #set() operations will change the content of the Context? (which isn't
>> thread safe)
> 
> The Context is stateful, and its state is presumably stored in an
> unsynchronized map.  The cost of making it thread-safe doesn't seem to be
> worth it for the 0.01% of users who will be sharing the context across
> threads.  For them, its easy enough to synchronize all operations that
> would affect the Context.

Exactly.  And that's 'VelocityContext'.

> 
>> I haven't stress tested the hell out of it but I have a "default" context
>> (with a bunch of global variables, tools, etc...) that I nest inside of the
>> context that is created during each request ...
>> 
>> VelocityContext ctx = new VelocityContext(defaultContext);
>> 
>> is that safe?
> 
> A more complicated question.  Without looking at the code (look ma, no
> hands), I'd say this operation is technically only safe if the following
> conditions are met:
> - the default context is constructed before other threads that use it are
> created,
> - nothing is ever added to or removed from the default context after it
> is initially created and populated,
> - the objects that the default context references are similarly immutable.
> 
> (In reality, the first condition is probably not met, but there is almost
> certainly other synchronization that makes it work anyway, even though
> technically there could be race conditions on some architectures that would
> make it not thread-safe.)

#2 and #3 are probably not required, but I just got home and haven't given
it deep thought. 


geir

-- 
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
"Whoever would overthrow the liberty of a nation must begin by subduing the
freeness of speech." - Benjamin Franklin



Re: Thread safety

Posted by Christoph Reck <Ch...@dlr.de>.
David Esposito wrote:
>[snip]
> Well, what i'm actually referring to is creating a my defaultContext inside
> of my Servlet init() method. Which, i believe (but wouldn't swear to without
> reading the spec), is guaranteed to execute before any of attempt to "use"
> the context via the doPost/doGet  ... The objects I stick in there are, as
> you suggest, immutable ... examples include:
> 
> - list of states
> - list of countries
> - "tool" objects that contain formatting functions (static methods) ...
> 
> etc ...
> 
> so it sounds like, in my particular case, sharing a velocity context across
> threads is safe ..

Be careful here, since VelociMacros and foreach loops will write to the
context. Therefore sharing a context over threads is not recommendable.

Use a chainged VC over the static one in the case you whant to use 
a pre-initialized one over multiple threads.

> 
> phew ... dodged a bullet there ... ;)
> 
> -Dave

:) Christoph

RE: Thread safety

Posted by David Esposito <es...@newnetco.com>.

>
> >I haven't stress tested the hell out of it but I have a "default" context
> >(with a bunch of global variables, tools, etc...) that I nest
> inside of the
> >context that is created during each request ...
> >
> >VelocityContext ctx = new VelocityContext(defaultContext);
> >
> >is that safe?
>
> A more complicated question.  Without looking at the code (look ma, no
> hands), I'd say this operation is technically only safe if the following
> conditions are met:
>   - the default context is constructed before other threads that
> use it are
> created,
>   - nothing is ever added to or removed from the default context after it
> is initially created and populated,
>   - the objects that the default context references are similarly
> immutable.
>
> (In reality, the first condition is probably not met, but there is almost
> certainly other synchronization that makes it work anyway, even though
> technically there could be race conditions on some architectures
> that would
> make it not thread-safe.)
>

Well, what i'm actually referring to is creating a my defaultContext inside
of my Servlet init() method. Which, i believe (but wouldn't swear to without
reading the spec), is guaranteed to execute before any of attempt to "use"
the context via the doPost/doGet  ... The objects I stick in there are, as
you suggest, immutable ... examples include:

- list of states
- list of countries
- "tool" objects that contain formatting functions (static methods) ...

etc ...

so it sounds like, in my particular case, sharing a velocity context across
threads is safe ..

phew ... dodged a bullet there ... ;)

-Dave


RE: Thread safety

Posted by Brian Goetz <br...@quiotix.com>.
>Is there something fancy that goes on with the Context during the merge()
>that would make it non-thread-safe? Or is it just concern over the fact that
>#set() operations will change the content of the Context? (which isn't
>thread safe)

The Context is stateful, and its state is presumably stored in an 
unsynchronized map.  The cost of making it thread-safe doesn't seem to be 
worth it for the 0.01% of users who will be sharing the context across 
threads.  For them, its easy enough to synchronize all operations that 
would affect the Context.

>I haven't stress tested the hell out of it but I have a "default" context
>(with a bunch of global variables, tools, etc...) that I nest inside of the
>context that is created during each request ...
>
>VelocityContext ctx = new VelocityContext(defaultContext);
>
>is that safe?

A more complicated question.  Without looking at the code (look ma, no 
hands), I'd say this operation is technically only safe if the following 
conditions are met:
  - the default context is constructed before other threads that use it are 
created,
  - nothing is ever added to or removed from the default context after it 
is initially created and populated,
  - the objects that the default context references are similarly immutable.

(In reality, the first condition is probably not met, but there is almost 
certainly other synchronization that makes it work anyway, even though 
technically there could be race conditions on some architectures that would 
make it not thread-safe.)



--
Brian Goetz
Quiotix Corporation
brian@quiotix.com           Tel: 650-843-1300            Fax: 650-324-8032

http://www.quiotix.com


Re: Thread safety

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 10/1/01 4:58 PM, "Nick Bauman" <ni...@cortexity.com> wrote:

>> On 10/1/01 4:24 AM, "Bojan Smojver" <bo...@binarix.com> wrote:
>> 
>>> Are Template.merge() and VelocityEngine.getTemplate() thread safe?
>>> 
>>> Bojan
>> 
>> merge() is as long as you don't share a VelocityContext across
>> simultaneous threads.
> 
> Which means the answer is "no" ;)

No, it means the answer is

"merge() is as long as you don't share a VelocityContext across simultaneous
threads."

If you make up your own, threadsafe Context, then yes, merge() is safe.
It's VelocityContext that isn't

Lets face it - you don't want to have one thread using a VC in merge() while
another is modifying data.  merge() won't guarantee anything about the VC.

> 
> You have really only 2 choices for the web:
> 
> a) Create a new VelocityContext for each http request
> b) Pool VelocityContexts and recycle them. Since they already implement
> clone() very nicely, this should be easy.

Yep.  And making a VC with each request isn't that expensive.

Another option is to stuff the VC into the session for the user....

> 
> There is one more choice, but it's not a real one:
> 
> c) serialize access to the context --  not really an option on the web

No, that's not good.


Geir

 
> 
>> getTemplate() should be as well.
>> 
>> Er, why?  Problems?
>> 
>> -- 
>> Geir Magnusson Jr.     geirm@optonline.net
>> System and Software Consulting
>> "Whoever would overthrow the liberty of a nation must begin by subduing
>> the freeness of speech." - Benjamin Franklin
> 
> 

-- 
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
"They that can give up essential liberty to obtain a little temporary safety
deserve neither liberty nor safety." - Benjamin Franklin



Re: Thread safety

Posted by Nick Bauman <ni...@cortexity.com>.
> On 10/1/01 4:24 AM, "Bojan Smojver" <bo...@binarix.com> wrote:
> 
>> Are Template.merge() and VelocityEngine.getTemplate() thread safe?
>> 
>> Bojan
> 
> merge() is as long as you don't share a VelocityContext across
> simultaneous threads.

Which means the answer is "no" ;) 

You have really only 2 choices for the web:

 a) Create a new VelocityContext for each http request
 b) Pool VelocityContexts and recycle them. Since they already implement
clone() very nicely, this should be easy.

There is one more choice, but it's not a real one:

 c) serialize access to the context --  not really an option on the web


> getTemplate() should be as well.
> 
> Er, why?  Problems?
> 
> -- 
> Geir Magnusson Jr.     geirm@optonline.net
> System and Software Consulting
> "Whoever would overthrow the liberty of a nation must begin by subduing
> the freeness of speech." - Benjamin Franklin



Re: Thread safety

Posted by Bojan Smojver <bo...@binarix.com>.
"Geir Magnusson Jr." wrote:
> 
> On 10/1/01 4:24 AM, "Bojan Smojver" <bo...@binarix.com> wrote:
> 
> > Are Template.merge() and VelocityEngine.getTemplate() thread safe?
> >
> > Bojan
> 
> merge() is as long as you don't share a VelocityContext across simultaneous
> threads.
> 
> getTemplate() should be as well.

I'm making a fresh instance of the VC every time there is a new request.
Not the most efficient thing to do but rather simple. It's been
performing well on a P2 266, so I'll keep that for now.

> Er, why?  Problems?

No, the more I use Velocity, the better it gets... I just wanted to make
sure I'm doing the proper thing...

I'm not sure if you follow Tomcat Dev list, but there was a recent
report about problems with SingleThreadModel. I used to use it to ensure
thread synchro in my servlet, but after I read the code, I've realized
it would result in dreadful performance since the whole service method
would be synchronised.

I remember good old JServ which used pools, so I thought Tomcat was
doing the same. Which, of course, is utter nonsense, since they are two
totally different pieces of software.

Anyway, I've decided to go with non-SingleThreadModel servlet, but I
just have to be a bit more careful with a few things. When the (first
ever - for the container that supports pools) servlet instance in an
application is initiated, I create an instance of VelocityEngine and
store it into ServletContext. This VE is used by all servlet instances
(if pool approach is used by the container) or by all threads to
getTemplate(). If it's thread safe, I can have one of those and all is
fine. (Actually when I think about this a bit more, I would have had
problems when pool of servlets was used even if using SingleThreadModel,
provided getTemplate() wasn't thread safe)

Once the Template is fetched, it has to be merged by calling the merge()
method. Since this Template was fetched from the same instance of
VelocityEngine, it is possibly referring to the same object in its cache
as Template from some other thread/instance.

VelocityContext is always a local variable, created on the stack, so
freshness is guaranteed there. If there are no writes to Template by
merge() and no writes to VelocityEngine by getTemplate(), which can
upset this scenario, all should be fine.

Although I'm replying to Geir, I would like to thank all people that
spend their time contributing to this discussion.

Bojan

Re: Thread safety

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 10/1/01 5:02 PM, "David Esposito" <es...@newnetco.com> wrote:

> Is there something fancy that goes on with the Context during the merge()
> that would make it non-thread-safe? Or is it just concern over the fact that
> #set() operations will change the content of the Context? (which isn't
> thread safe)

There is a fancy-thing going on - the 'context local' caching of
introspection info.  The VC learns as it travels around the AST.  Since
nothing requires you to put the same objects into the context for a given
reference for a given template, you could do some harm...  That's where the
risk is.

And be careful that this doesn't lead to misinformation - it's only with the
VelocityContext, not the Context in general.  VC has the context local cache
built in, so that you can reuse it for for efficiency.  Just making your own
Context and passing that in will be fine.  Vel takes care of it...

> 
> I haven't stress tested the hell out of it but I have a "default" context
> (with a bunch of global variables, tools, etc...) that I nest inside of the
> context that is created during each request ...
> 
> VelocityContext ctx = new VelocityContext(defaultContext);
> 
> is that safe?

Yes - because the outer context picks up the goo, so the inner stays clean.

geir
 
>> -----Original Message-----
>> From: Geir Magnusson Jr. [mailto:geirm@optonline.net]
>> Sent: Monday, October 01, 2001 6:00 AM
>> To: velocity-user@jakarta.apache.org
>> Subject: Re: Thread safety
>> 
>> 
>> On 10/1/01 4:24 AM, "Bojan Smojver" <bo...@binarix.com> wrote:
>> 
>>> Are Template.merge() and VelocityEngine.getTemplate() thread safe?
>>> 
>>> Bojan
>> 
>> merge() is as long as you don't share a VelocityContext across
>> simultaneous
>> threads.
>> 
>> getTemplate() should be as well.
>> 
>> Er, why?  Problems?
>> 
>> --
>> Geir Magnusson Jr.     geirm@optonline.net
>> System and Software Consulting
>> "Whoever would overthrow the liberty of a nation must begin by
>> subduing the
>> freeness of speech." - Benjamin Franklin
>> 
>> 
> 

-- 
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
"Whoever would overthrow the liberty of a nation must begin by subduing the
freeness of speech." - Benjamin Franklin



RE: Thread safety

Posted by David Esposito <es...@newnetco.com>.
Is there something fancy that goes on with the Context during the merge()
that would make it non-thread-safe? Or is it just concern over the fact that
#set() operations will change the content of the Context? (which isn't
thread safe)

I haven't stress tested the hell out of it but I have a "default" context
(with a bunch of global variables, tools, etc...) that I nest inside of the
context that is created during each request ...

VelocityContext ctx = new VelocityContext(defaultContext);

is that safe?

> -----Original Message-----
> From: Geir Magnusson Jr. [mailto:geirm@optonline.net]
> Sent: Monday, October 01, 2001 6:00 AM
> To: velocity-user@jakarta.apache.org
> Subject: Re: Thread safety
>
>
> On 10/1/01 4:24 AM, "Bojan Smojver" <bo...@binarix.com> wrote:
>
> > Are Template.merge() and VelocityEngine.getTemplate() thread safe?
> >
> > Bojan
>
> merge() is as long as you don't share a VelocityContext across
> simultaneous
> threads.
>
> getTemplate() should be as well.
>
> Er, why?  Problems?
>
> --
> Geir Magnusson Jr.     geirm@optonline.net
> System and Software Consulting
> "Whoever would overthrow the liberty of a nation must begin by
> subduing the
> freeness of speech." - Benjamin Franklin
>
>


Re: Thread safety

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 10/1/01 4:24 AM, "Bojan Smojver" <bo...@binarix.com> wrote:

> Are Template.merge() and VelocityEngine.getTemplate() thread safe?
> 
> Bojan

merge() is as long as you don't share a VelocityContext across simultaneous
threads.

getTemplate() should be as well.

Er, why?  Problems?

-- 
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
"Whoever would overthrow the liberty of a nation must begin by subduing the
freeness of speech." - Benjamin Franklin