The question is published on by Tutorial Guruji team.
I have an acync method with callback:
myAsyncMethod(params) { handleResult(it) }
I need to convert it to sync method (block and return result) like this:
val result = mySyncMethod(params) handleResult(result)
I can’t re-implement it by another way because this method provided by third-party library.
I am trying to use ReentrantLock:
fun mySyncMethod(params:Type) { Log.d("tag", "1") val result = null val mutex = ReentrantLock() myAsyncMethod(params) { Log.d("tag", "3") result = it mutex.unlock() } Log.d("tag", "2") mutex.lock() Log.d("tag", "4") return result } handleResult(mySyncMethod(params))
I wait that I should see 1, 2, 3, 4. But I get 1, 2, 4, 3 and null in handleResult. I am trying the same with mutex but with the same result. How to make it works?
P.S. Sure I can use synchronized, but in this case I have to use Object-variable additionally.
Answer
I expect that I should see 1, 2, 3, 4.
Then you misunderstood what ReentrantLock
is actually for.
If mySyncMethod
can be called from different threads, then after mutex.lock()
is called, only one thread at a time can execute the code following mutex.lock()
– the other threads executing this method have to wait. Once mutex.unlock()
is called, one of the waiting threads will execute the code too and so on.
So, the thread owning the mutex
forces the other threads to wait but its own flow isn’t blocked. myAsyncMethod
starts running after the outer method has completed already and hence result
is still null
.
I need to convert it to sync method (block and return result) like this:
According to your requirements, you need to block the current thread until the async task is complete. To achieve this, you could use Semaphore or CountDownLatch. For example, with Semaphore
, your method could look as follows:
fun mySyncMethod(params:Type) { Log.d("tag", "1") val result = null val semaphore = Semaphore(0) myAsyncMethod(params) { Log.d("tag", "3") result = it semaphore.release() } Log.d("tag", "2") semaphore.acquireUninterruptibly() Log.d("tag", "4") return result }