Kotlin Lazy — What are they? How to use them?

Vishal Ratna
4 min readApr 30, 2020

--

Too lazy to write anything!

Photo by Kate Stone Matheson on Unsplash

Want to know about kotlin lateinit, here is some juice for you:

Sometimes we encounter a scenario where we want to avoid initializations of some fields in a class till they are actually needed. A classic example could be, the case of heavy singletons. Why do you want to initialize your database manager class before you do any DB operations in your application? In mobile applications, the lazy loading of heavy classes gives you a performance edge as it improves the app load time. App loads whatever is required bare minimum to present the screen to the user.

We are familiar with the approach of lazy loading in the double-checked locking techniques in the Singleton pattern in Java. Let us see how it looks like.

MockManager.java

This class does a couple of things.

  1. Does the initialization of the MockManager once, and the next time user calls it, it returns the stored instance from the memory.
  2. It takes care of synchronization issues, even if multiple threads call instance() to create mockmanager, only one thread gets the chance to create it and rest use the stored instance.
  3. The instance is created when you actually use the class ie lazily created.

But the question is, can we this for all classes in which we want to implement these properties. It would be too tedious and a lot of code. Here kotlin’s lazy delegates shine.

Let’s see how this functionality, when implemented through lazy, would look like.

Lazy mock manager implementation using kotlin lazy delegates.

The code is minimal. But it comes with some drawbacks.

  1. The first access to mockmanager is synchronized, if you do not have concurrency in your code, that will add an additional cost which is unnecessary.
  2. If you try to synchronize the code with returned instance ie. mockmanager externally it might result in deadlock. If thread encounters an exception, while creating the instance, the kotin framework safely releases the lock. We will deal with the internal details in the next post. If we want to provide any external lock object we can very well do that like this, but be wary of the consequences:

So now we know, that we should not be filling our code with lazy delegates otherwise, it is going to add synchronization in places where there is no concurrency at all. So what is the solution to that?

Lazy without synchronization

When you use the mode NONE, be very sure that you do not have multiple threads competing to initialize the value, otherwise results will be unpredictable!

In the context of android, I see lots of variables that I have to initialize eagerly in the lifecycle callbacks, which can be deferred to the point where it is first accessed. Lazy.NONE is a good choice for those cases. Given we are executing on MainThread.

There are 3 such modes possible:

1. LazyThreadSafetyMode.SYNCHRONIZED (thread-safe)
2. LazyThreadSafetyMode.PUBLICATION (thread-safe)
3. LazyThreadSafetyMode.NONE (non thread-safe)

We have already talked about 1 and 3, now let’s talk about Publication mode.

In the case of mode Synchronized, multiple threads are not allowed to run the initializer lambda, only one thread is allowed inside the monitor, it executes the initializer and other threads use the stored value. Contrary to that, there is no such restriction there in Publication, multiple threads are allowed to run the initializer lambda but the first one to create the instance wins, and that value is published as used by other threads. This mode is also thread-safe. So, confused? When to use Synchronized and when to use Publication?

Both the modes provide thread safety, but in case of publication, the initializer is run more than once till the value gets initialized after that the same stored value is returned. If you feel that running your calculation in multiple threads simultaneously might eat up processor resources due to the nature of your initializer then go for synchronized, else if code is on the lighter side publication can give you thread safety without the cost of locking.

One thing to note is the kotlin initializer functions provided as lamdas are represented as anonymous inner classes and capture the outer scope and are released once the instance is created. If your initializer function does something heavy and time consuming, then take care of memory leaks also. It could leak memory!

Kotlin lambdas do not get benefits of java’s InvokeDynamic call which java lambdas take.

INVOKESPECIAL HandleKt$main$listOfStudents$2.<init> (LStudent;)V
CHECKCAST kotlin/jvm/functions/Function0
INVOKESTATIC kotlin/LazyKt.lazy (Lkotlin/LazyThreadSafetyMode;Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;

So, how can we do all these things in Java? Can we do something about it? We will get to know the answer to all these questions in the below post.

https://medium.com/@kiitvishal89/implementing-kotlin-lazy-like-functionality-in-java-8b23185ba1f7

--

--

Vishal Ratna

Senior Android Engineer @ Microsoft. Fascinated by the scale and performance-based software design. A seeker, a learner. Loves cracking algorithmic problems.