https://kotlinlang.org logo
Title
m

mike_shysh

12/02/2019, 1:57 PM
Hi, Please help me to find out what is the best way to implement thread-safe singleton (for DB connection)? Here are the variants:
object DBProvider {
    @Volatile private var dbSession: Session? = null

    fun getDBSession(): Session = dbSession ?: synchronized(this) {
        dbSession ?: when (dbType) {
            DBTypes.MYSQL.type -> MySqlSession(host = dbHost, port = dbPort).getSession()
            DBTypes.ORACLE.type -> OracleSession(host = dbHost, port = dbPort).getSession()
            else -> throw Exception("Unsupported DB type - $dbType.")
        }.also { dbSession = it }
    }
...
d

diesieben07

12/02/2019, 1:58 PM
Simplest way would be
val dbSession by lazy { /* create session here */ }
, which is thread-safe by default.
☝️ 2
m

mike_shysh

12/02/2019, 1:58 PM
lateinit is the same?
private lateinit var dbSession: Session
d

diesieben07

12/02/2019, 1:59 PM
No, lateinit is simply syntax-sugar for a nullable field.
lazy
has synchronization built-in
m

mike_shysh

12/02/2019, 1:59 PM
Thanks, I will try
Should this
dbSession
be a static variable, or it does not matter?
d

diesieben07

12/02/2019, 2:02 PM
Kotlin does not have the concept of static fields
m

mike_shysh

12/02/2019, 2:03 PM
I know, but I want concept of singleton to work
object DBProvider
its a singleton class
d

diesieben07

12/02/2019, 2:03 PM
Since you are doing this in an
object
, there will only be one instance of that
object
and thus only one value for each of it's properties
m

mike_shysh

12/02/2019, 2:03 PM
but what about properties
yeah
Will it be ok when one thread use dbSession from
object DBProvider
and at this very time another thread tries to obtain dbSession
d

diesieben07

12/02/2019, 2:06 PM
That's why
lazy
has synchronization built in. It guarantees only one value will ever be created
Even in concurrent scenarios
m

mike_shysh

12/02/2019, 2:07 PM
So, I do not need custom getter for
dbSession
Am I right?
d

diesieben07

12/02/2019, 2:07 PM
Yes, if you use
by lazy { }
m

mike_shysh

12/02/2019, 2:08 PM
I can just put this into
by lazy {  }
init
fun getDBSession(): Session {
dbSession = when (dbType) {
                DBTypes.MYSQL.type -> MySqlSession(host = dbHost, port = dbPort).getSession()
                DBTypes.ORACLE.type -> OracleSession(host = dbHost, port = dbPort).getSession()
                else -> throw Exception("Unsupported DB type - $dbType.")
            }
        }
        return dbSession
}
d

diesieben07

12/02/2019, 2:09 PM
Yes
🔥 1
m

mike_shysh

12/02/2019, 2:09 PM
Thanks
There are lots of info on the internet, but its hard to catch the idea)