官术网_书友最值得收藏!

  • Functional Kotlin
  • Mario Arias Rivu Chakraborty
  • 384字
  • 2021-06-24 19:15:29

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:

主站蜘蛛池模板: 长白| 清河县| 新津县| 杨浦区| 渝中区| 腾冲县| 贡觉县| 澄城县| 耿马| 高碑店市| 江北区| 封开县| 封开县| 中方县| 芜湖市| 建平县| 讷河市| 观塘区| 亚东县| 织金县| 寻乌县| 元氏县| 平罗县| 浪卡子县| 班戈县| 茌平县| 元朗区| 扶余县| 康马县| 若尔盖县| 天等县| 沛县| 萨迦县| 藁城市| 偃师市| 和田市| 屏南县| 乌兰县| 沽源县| 保康县| 吴桥县|