- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Implementation of lazy val within an object's method
Wed, 2011-10-05, 15:42
Hi.
I have recently faced a strange thread blocking issue. Sorry if this
issue has been already discussed before, I couldn't find it.
Let's say we have this object:
object Test {
def func() {
lazy val a = someExpensiveCalculations
// now we use (or not) this lazy val, for example:
println(a)
}
private def someExpensiveCalculations = 1
}
Scala compiler creates this code (after decompilation):
public final class Test$ implements ScalaObject {
public void func() {
IntRef a$lzy$1 = new IntRef(0);
VolatileIntRef bitmap$0$1 = new VolatileIntRef(0);
Predef$.MODULE$.println(BoxesRunTime.boxToInteger(a$1(a$lzy$1,
bitmap$0$1)));
}
private final int a$1(IntRef intref, VolatileIntRef
volatileintref)
{
if((volatileintref.elem & 1) == 0)
synchronized(this)
{
if((volatileintref.elem & 1) == 0)
{
intref.elem = someExpensiveCalculations();
volatileintref.elem = volatileintref.elem | 1;
}
BoxedUnit _tmp = BoxedUnit.UNIT;
}
return intref.elem;
}
// other unimportant stuff
}
The main part here is "synchronized(this)".
It means that if I call Test.func() from many concurrent threads, It
will lead to blocking, because they all use one monitor.
For me, this is very strange, because "val a" is a local variable of
method func(), and each call of this method will create a new instance
of a, and all these instances are absolutely independent.
Therefore I think it should use other object for synchronization
(unique for each call of func()), not singleton Test, because current
implementation leads to huge synchronization overhead in highly
concurrent systems.
Wed, 2011-10-05, 17:17
#2
Re: Implementation of lazy val within an object's method
On Wed, Oct 5, 2011 at 8:23 AM, Hubert Plociniczak
wrote:
> it looks like the tree generator for double checked locking always followed
> this template (i.e. synchronize on the enclosing class).
> Not sure if there is a deeper reason for that or did we just follow java
> implementation exactly and forgot about it. Please create a bug, I will have
> a look.
There are already multiple tickets open, which look pretty combinable.
https://issues.scala-lang.org/browse/SUGGEST-8
https://issues.scala-lang.org/browse/SUGGEST-11
Wed, 2011-10-05, 17:57
#3
Re: Implementation of lazy val within an object's method
Hi Hubert, Paul.
Thanks for your replies.
Yes, those tickets describe the same problem.
Vladimir.
On Oct 5, 8:11 pm, Paul Phillips wrote:
> On Wed, Oct 5, 2011 at 8:23 AM, Hubert Plociniczak
>
> wrote:
> > it looks like the tree generator for double checked locking always followed
> > this template (i.e. synchronize on the enclosing class).
> > Not sure if there is a deeper reason for that or did we just follow java
> > implementation exactly and forgot about it. Please create a bug, I will have
> > a look.
>
> There are already multiple tickets open, which look pretty combinable.
>
> https://issues.scala-lang.org/browse/SUGGEST-8
> https://issues.scala-lang.org/browse/SUGGEST-11
Thu, 2011-10-06, 09:37
#4
Re: Implementation of lazy val within an object's method
On 10/05/2011 06:11 PM, Paul Phillips wrote:
> On Wed, Oct 5, 2011 at 8:23 AM, Hubert Plociniczak
> wrote:
>> it looks like the tree generator for double checked locking always followed
>> this template (i.e. synchronize on the enclosing class).
>> Not sure if there is a deeper reason for that or did we just follow java
>> implementation exactly and forgot about it. Please create a bug, I will have
>> a look.
> There are already multiple tickets open, which look pretty combinable.
>
> https://issues.scala-lang.org/browse/SUGGEST-8
> https://issues.scala-lang.org/browse/SUGGEST-11
Good to know. I didn't have them on my radar.
Hi,
it looks like the tree generator for double checked locking always
followed this template (i.e. synchronize on the enclosing class).
Not sure if there is a deeper reason for that or did we just follow java
implementation exactly and forgot about it. Please create a bug, I will
have a look.
hubert
On 10/05/2011 04:42 PM, Vladimir Sorokin wrote:
> Hi.
>
> I have recently faced a strange thread blocking issue. Sorry if this
> issue has been already discussed before, I couldn't find it.
> Let's say we have this object:
> object Test {
> def func() {
> lazy val a = someExpensiveCalculations
> // now we use (or not) this lazy val, for example:
> println(a)
> }
> private def someExpensiveCalculations = 1
> }
>
> Scala compiler creates this code (after decompilation):
> public final class Test$ implements ScalaObject {
> public void func() {
> IntRef a$lzy$1 = new IntRef(0);
> VolatileIntRef bitmap$0$1 = new VolatileIntRef(0);
> Predef$.MODULE$.println(BoxesRunTime.boxToInteger(a$1(a$lzy$1,
> bitmap$0$1)));
> }
>
> private final int a$1(IntRef intref, VolatileIntRef
> volatileintref)
> {
> if((volatileintref.elem& 1) == 0)
> synchronized(this)
> {
> if((volatileintref.elem& 1) == 0)
> {
> intref.elem = someExpensiveCalculations();
> volatileintref.elem = volatileintref.elem | 1;
> }
> BoxedUnit _tmp = BoxedUnit.UNIT;
> }
> return intref.elem;
> }
> // other unimportant stuff
> }
>
> The main part here is "synchronized(this)".
> It means that if I call Test.func() from many concurrent threads, It
> will lead to blocking, because they all use one monitor.
> For me, this is very strange, because "val a" is a local variable of
> method func(), and each call of this method will create a new instance
> of a, and all these instances are absolutely independent.
> Therefore I think it should use other object for synchronization
> (unique for each call of func()), not singleton Test, because current
> implementation leads to huge synchronization overhead in highly
> concurrent systems.