4

Wild Storage | Part 2 — Threading and Concurrency

 3 years ago
source link: https://medium.com/knowing-android/wild-storage-part-2-threading-and-concurrency-40f38992ca2d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Wild Storage | Part 2 — Threading and Concurrency

For Android developers

Easy data layer for every Application, here is the list of the blogs in this series:

0*pLF8sX1aUCdp29kd.jpeg?q=20
wild-storage-part-2-threading-and-concurrency-40f38992ca2d
This image is from Unsplash

This is the second part of the series “Wild Storage for Android developers” today we are gonna discuss Threading and Concurrency specifically for how coroutines work for Room

Putting some details about the last part, usually, we end up with something like this in Mobile applications, we may have a suspendable function that goes to an API, and once this answers the expected result we may want to put some data inside a database.

1*bljjvyQt9dc4_P1rIkKd5Q.png?q=20
wild-storage-part-2-threading-and-concurrency-40f38992ca2d

We don’t want funky performance, our users will notice if we have some trouble loading our views, usually, about 60 frames per second our users can perceive the change of frames as smooth if our tasks are taking more than 16 milliseconds (not only fetch from the database but also network calls, maybe loading a view or even startup time) this can cause us trouble on a big scale especially cause all our users will notice, so we may use some threading to handle this part in a successful way like I say in the first part of this serial you can use Coroutines to create a suspend function inside Room, but we need to talk about multiprocessing and threading first!

Threads

Multiprocessing is the use of CPUs inside a computer, is the ability inside the hardware to support more than one processor and allocate tasks between them, all smartphones have processors.

Depending on the hardware, the operating system, and the software design we are building we have may have some considerations to determine the symmetry of the multiprocessing system, some may be equal, others may be reserved. For example, we may decide that we only going to have one particular CPU respond to all actions, which will make this multiprocessing app easier to make, but it will make the app less efficient than others in which all CPUs are utilized with multiple processors allocated, the reason is quite simple, cause if we have the ability to set up all the process we will be able to create more that one thread of execution within a process, giving space to something called multi-threading.

Whatsoever between process, we may have multiple threads, then Thread #1 start his execution, we may have to create another Thread #2 to execute a secondary task, you can’t execute more than one thread at the exact same time, there’s a reason for this!

1*DJErkgVsGzIhGUadC-L-fQ.png?q=20
wild-storage-part-2-threading-and-concurrency-40f38992ca2d

Everything that may happen in multiprocess architecture need at least this three parts: Scheduler, Processor, and Dispatcher, the first one is in charge of priorities like his name says is the method that will be assigned to resources that complete the work, and makes sure that all the threads get to run and get to finish, the Processor is the process of allocation of the task, and the Dispatcher make sure that set up all the threads in the specific allocation context we need to be executed, for Android in specific, we may have some operations that need to run in the user interface context and another outside of this one, the first one, is a thread that is full user-facing is called UI thread, runs inside the On Resume and Foreground of our apps and can dispatch other threads that may run in the background. All our apps need a basic thread to start and this will change, only if we explicitly switch threads inside the code, for example, the use of the keyword suspend will switch the thread, this also applies for callbacks in RxJava or any Thread, Run, or Handler function, this applies for databases, network calls and mostly everything that we want to do to have a good performance in terms of user experience if we block UI Thread for too long this can cause the app to get blocked completely, this action is known as an ANR’s problems.

ANR problems can be tracked inside the Google Play Console in the Android Vitals part, and as quoted in the documentation

Android vitals considers ANRs excessive when an app:

Exhibits at least one ANR in at least 0.47% of its daily sessions.
Exhibits 2 or more ANRs in at least 0.24% of its daily sessions.

We are not gonna talk about ANR right now, but I will write a new serial in a couple of weeks called “Spikes of Performance” when we are going to revisit all the problems we may have not only in threading but also in loading views and writing files.

Handling threading and concurrency of confined threads in the database is a primordial key part for a good performance, which some database like Realm already have callbacks that can be used to execute transactions in a kind way, for Room we need to use Coroutines

Coroutines

Not only Coroutines are the recommended solution for Kotlin development they are also really simple to approach cause basically a coroutine is thin threads and can be used in Room, whatsoever this is not obligatory, cause Room has the possibility to use Synchronous and Asynchronous methods with only using the key world suspend

These two functions look exactly the same, but let’s review the code.

1*rHx_Wm0jjKXOY48GRG7PmA.png?q=20
wild-storage-part-2-threading-and-concurrency-40f38992ca2d

Synchronous vs Asynchronous
We know that Room autogenerates code to helps us with the integration processes and to take the boilerplate that was implied when we use to do SQLite on Android, one of the most important parts of this, cause these two images are the autogenerated code from Room for a non-suspend function and a suspend function

1*Y2SNz_uHSDzun5mvyFOPIw.png?q=20
wild-storage-part-2-threading-and-concurrency-40f38992ca2d

The first one and second one are pretty much similar in these specific parts that represent the generated code of an Insert to a table, this does not change even in asynchronous or synchronous code:

  • beginTransaction — Begins a transaction in EXCLUSIVE mode, this mode is pretty similar to IMMEDIATE modes in SQLite, in that a write transaction is started at the moment that is called, except that this mode prevents other database connections from reading the database while the transaction is underway.
  • insert — That will insert the object inside the required table
  • setTransactionSuccessful — Marks the current transaction as successful
  • endTransaction — End a transaction that was created at the beginning with the first method

As an Asynchronousfunction, we can appreciate that the code executed is happening in the UI thread, there’s no callback at all and for this specific Insert we may think this will not cause any ARN or any notorious performance bug, you may be correct, whatsoever, other patterns can cause this to create a problem that we can easily correct using a coroutine, for example, in the second image, the generated code has a callback with a new type called — Continuation that pretty much creates an interface representing a continuation after a suspension point that returns a value of type T as an instance with the given context (a dispatcher for the coroutine) and implementation of resumeWith method, and just like that, the Insert will happen outside the UI Thread and we will not allocate any retention frames.

We are still missing the other execute knows as CoroutinesRooom is the part in charge of switching to another dispatcher, depending on whether the status of the database, remember we can have an open, in the middle of a transaction or a closed database. If the function we are trying to execute is the first two options, Room will do the Insert right away, for the other status, Room will make sure that everything is happening in a secondary thread using a different dispatcher for the transaction, the generated code looks something like this, you can found this code in the Open Source code of Room

1*_cx-q6jFRCQnG59TpiCZog.png?q=20
wild-storage-part-2-threading-and-concurrency-40f38992ca2d

Concurrency

We have been talking about the importance of having a secondary thread to execute our task, especially in databases, cause in Android’s SQLite transactions are thread confined if a coroutine is paused there a possibility that the resumed coroutine will not be executed in the same thread.

1*JH7RXZ2ztG1z69f6LPVtkw.gif?q=20
wild-storage-part-2-threading-and-concurrency-40f38992ca2d

Let’s give it a look at this gif, we may have an Update and a Delete from a click and this will be executed in threads, we may want to have all this process in one ☝️ and only thread.
But imagine we end up with another click that will Insert other data, the first Update will execute in Thread #1 but if the Insert happens between the Update and Delete, the Insert will use Thread #1 because is not currently in use, so the Delete will not happen in Tread # 1 will happen in Thread #2 and this is also known as a concurrency problem, cause we may not know if the Delete was successful and this can cause a deadlock

What we need to do to make sure Update and Delete happens in the same thread is running these two methods inside a transaction.

1*NlPhpsl_J8MGTuFUF3IeNg.png?q=20
wild-storage-part-2-threading-and-concurrency-40f38992ca2d

A transaction will make sure to execute and only mark as successful as many methods that are depending on each other and they will be executed in a specific dispatcher that will guarantee that all the methods will be brought in the same thread.

The transaction can also be used as an annotation inside a DAO with abstract functions as mentioned in the documentation

This is all for this part of the post. For the last part, we will discuss Datastore and Shared preferences and I will talk a little about the security behind this!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK