Thread safety

We have probably seen a thousand times that immutability brings thread safety to the table along with it. What does it actually mean and how does immutability achieve thread safety? Working with multiple threads is itself a complex job. When you are accessing a class from multiple threads, you need to ensure certain things, like locking and releasing of the object and synchronization, but none of them are required if you are accessing any immutable data from multiple threads.

Confused? Let's have an example with threads and mutable data:

class MyData { 
    var someData:Int = 0 
} 
 
fun main(args: Array<String>) { 
    val myData:MyData = MyData() 
 
    async(CommonPool) { 
        for(i in 11..20) { 
            myData.someData+=i 
            println("someData from 1st async ${myData.someData}") 
            delay(500) 
        } 
    } 
 
    async(CommonPool) { 
        for(i in 1..10) { 
            myData.someData++ 
            println("someData from 2nd async ${myData.someData}") 
            delay(300) 
        } 
    } 
 
    runBlocking { delay(10000) } 
} 

In this program, we've used two coroutines (we will cover coroutines in detail in Chapter 7Asynchronous Processing with Coroutines) which works on the same mutable data. Let's have a look in the following output and then we will describe and discuss the problems in this program:

So, look closely at the output. As both the coroutines works simultaneously on myData.someData, data consistency is not ensured in either one.

The traditional solution to this problem is to use locking-releasing techniques and synchronization, but then also you'll need to write a lot of code for that and to avoid deadlock while implementing locking and releasing of data.

Functional programming provides a one-stop solution to this problem through immutability. Let's have a look how immutability and local variables can save you in multithreading:

class MyDataImmutable { 
    val someData:Int = 0 
} 
 
fun main(args: Array<String>) { 
    val myData: MyDataImmutable = MyDataImmutable() 
 
    async(CommonPool) { 
        var someDataCopy = myData.someData 
        for (i in 11..20) { 
            someDataCopy += i 
            println("someData from 1st async $someDataCopy") 
            delay(500) 
        } 
    } 
 
    async(CommonPool) { 
        var someDataCopy = myData.someData 
        for (i in 1..10) { 
            someDataCopy++ 
            println("someData from 2nd async $someDataCopy") 
            delay(300) 
        } 
    } 
 
    runBlocking { delay(10000) } 
} 

We've modified the previous program to make someData immutable (as we're not using custom getter with this variable, so it will remain immutable) and used local variables inside both the coroutines.

Have a look at the following output; it clearly shows that the problem is solved:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.2.225