Guice @provides vs toProvider

2,033 views
Skip to first unread message

surya aditya

unread,
Jan 5, 2012, 12:18:40 AM1/5/12
to google-guice
Dear Friends,

In multithreaded environment in multi-core cpu machine, I found
@provides to be not-thread safe. However if I write Provider class and
bind using 'toProvider' then it is showing expected behavior.

Is this my right understanding that @Provides is not thread safe. Has
anybody experienced this before? By not thread safe I mean an instance
of an object is being reused when i use @provides, ofcourse this was
totally unacceptable as the Object has instance variable causing
inconsistencies.

Appreciate feedback.

Peace,
Surya

Sam Berlin

unread,
Jan 5, 2012, 10:09:35 AM1/5/12
to google...@googlegroups.com
There's nothing special about @Provides vs toProvider.  @Provides is just syntactic sugar for creating a Provider<T> instance and binding it with toProvider(instance).

There's nothing built into Guice to make Providers thread-safe.  If your provider has state that is mutated among different calls to provider.get(), you need to handle synchronization manually if you expect the provider to be called from different threads.  The same thing applies to the actual objects Guice injects (ie, non-providers).

I think the catch is that toProvider(SomeProvider.class) is an unscoped provider binding, so each injection of Provider<T> will create a new instance of the Provider (I think), so there's no shared state since each instance is different.  @Provides is analogous to toProvider(providerInstance), which in turn is analogous to bind(..).toInstance(..), all of which act as singletons and need to be thread-safe.

sam


--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.


surya aditya

unread,
Jan 8, 2012, 5:17:09 PM1/8/12
to google-guice
Thanks Sam. Your reply now adds clarity to my observations. I have
made changes, switched to toProvider(SomeProvider.class) as
requirement is for unique instances all the times in our case.

Regards,
Surya.

Sam Berlin

unread,
Jan 8, 2012, 5:45:24 PM1/8/12
to google...@googlegroups.com
I would check carefully that it is doing what you expect it to do in all scenarios, and be warned that in the future things may change.  I don't think Guice provides any guarantees as to the uniqueness of providers it creates from toProvider(YourProvider.class) bindings.

 sam

unguiculus

unread,
Jan 9, 2012, 4:45:21 AM1/9/12
to google-guice
Sam,

This is not quite correct. @Provides methods create unscoped instances
unless they are annotated with a scope annotation (e. g. @Singleton).
I think the documentation on this could be improved. It should
especially be mentioned that scoping is possible.

http://code.google.com/p/google-guice/wiki/ProvidesMethods

Reinhard

Sam Berlin

unread,
Jan 9, 2012, 9:05:41 AM1/9/12
to google...@googlegroups.com

The original poster was asking about the Provider itself, not the scope of what it provides.

sam

Derrick

unread,
Jan 10, 2012, 5:16:49 PM1/10/12
to google-guice
I have investigated this through experimentation. You can control the
scope of the Provider and/or the object being provided separately.

The following code ensures that a single Provider is created

bind(IConsumer.class).toProvider(ConsumerProvider.class);

bind(ConsumerProvider.class).asEagerSingleton();

While the following code ensures that BOTH the provider and the object
provided are singletons:


bind(IConsumer.class).toProvider(ConsumerProvider.class).asEagerSingleton();

While the following code ensures every injection of a provider and
every such object provided are distinct objects:

bind(IConsumer.class).toProvider(ConsumerProvider.class);

On Jan 9, 6:05 am, Sam Berlin <sber...@gmail.com> wrote:
> The original poster was asking about the Provider itself, not the scope of
> what it provides.
>
> sam

Leigh Klotz, Jr.

unread,
Jul 18, 2012, 6:08:00 PM7/18/12
to google...@googlegroups.com
One thing I've wanted for a long time in Guice is to specify the scope of the provided value with an annotation.

You can easily mark the scope of the Provider itself being with an annotation:

   @Singleton public class FooProvider implements Provider<Foo> { ... }

And in a Provider method, the scope annotation applies to the resulting object:
   @Provides @Singleton Foo getFoo() { ... }
 
You can do it in the module, with bind bind as described in Derrick's message below:
   bind(Foo.class).inScope(Scopes.SINGLETON);
   bind(Foo.class).toProvider(FooProvider.class);

But you can't mark it in annotations, at least as far as I can tell, unless you use an @Provides method.

It makes me want something like this:
  @Provides(@Singleton) public class FooProvider implements Provider<Foo> { ... }

Leigh.


Sam Berlin

unread,
Jul 18, 2012, 6:09:19 PM7/18/12
to google...@googlegroups.com
I could see maybe looking at the get() method for an annotation, but that becomes complicated with subclassing, etc.  Still, maybe worth it.
 sam

To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/g6po9YMzbvEJ.

To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages