I need a little help with understanding if multi-t...
# announcements
s
I need a little help with understanding if multi-threading might be causing me some problems with this class. Here is an example:
Copy code
@javax.inject.Singleton
class SpecificWork @Inject constructor() {

  private var cruncher: Cruncher? = null

  @GuardedBy("this")
  init {
    initCruncher()
  }

  @Synchronized
  private initCruncher() {
    // io work initialization
    cruncher = try {
      IOCruncher.init()
    } catch (e: IOException) {
      null
    }
  }

  fun doWork(): Result? {
    if (cruncher == null) {
      return null
    }

    // do work
    return Result("done")
  }
}
This
SpecificWorker
is provided via Dagger for dependency injection, but there could be many threads calling into it at the same time. I’m wondering • Is there a case where the
doWork()
started executing before the
initCruncher()
was able to assign the
cruncher
? Making the
cuncher
null and failing early?
t
why not put
Cruncher
on the graph as a
@Singleton
and let dagger's built in double check locking handle it for you?
Copy code
@Singleton
class SpecWork @Inject constructor(
  private val cruncher: Cruncher
) { 
    fun doWork(): Result {
      return Result("done")
    }
}
🤔 1
guess it depends when/why it would ever be ok for
IOCruncher.init()
to fail. maybe model it as
Optional<Cruncher>
?
s
I guess I could put the
Cruncher
in the graph as well. I’d probably make it more private in the graph so only my
SpecWork
has access to it. I don’t want to expose the
Cruncher
outside.
t
or just use a lazy prop delegate, same double check locking done for you. keeps your code simpler at least without exposing cruncher to the graph
Copy code
@Singleton
class SpecWork @Inject constructor() {

  private val cruncher: Cruncher by lazy {
      runCatching { IOCruncher.init() }.getOrNull()
  }

  fun doWork(): Result? {
    return cruncher?.run { ... }
  }
}