কোটলিন কর্টাইনগুলি "আগে-আগে" গ্যারান্টি দেয়?


10

কোটলিন কর্টাইনগুলি কোনও "ঘটনার আগে" গ্যারান্টি সরবরাহ করে?

উদাহরণস্বরূপ, mutableVarএই ক্ষেত্রে লিখিত এবং পরবর্তী থ্রেডে (সম্ভবত) অন্য থ্রেডের মধ্যে "ঘটনার আগে" গ্যারান্টি রয়েছে :

suspend fun doSomething() {
    var mutableVar = 0
    withContext(Dispatchers.IO) {
        mutableVar = 1
    }
    System.out.println("value: $mutableVar")
}

সম্পাদনা:

সম্ভবত অতিরিক্ত উদাহরণ প্রশ্নটি আরও পরিষ্কার করে তুলবে কারণ এটি আরও কোটলিন-ইশ (পরিবর্তনের বাইরে)। এই কোডটি থ্রেড-নিরাপদ:

suspend fun doSomething() {
    var data = withContext(Dispatchers.IO) {
        Data(1)
    }
    System.out.println("value: ${data.data}")
}

private data class Data(var data: Int)

নোট করুন যে JVM কোটলিনে চলার সময় জাভা হিসাবে একই মেমরি মডেল ব্যবহার করে।
স্লাও

1
@ স্লো, আমি জানি তবে হুডের নীচে প্রচুর যাদু চলছে। অতএব, আমি বুঝতে চাই যে এখানে কোনও ঘটনার আগে গ্যারান্টি রয়েছে যা আমি করটিইনগুলি থেকে পেয়েছি বা এটি সব আমার উপর রয়েছে।
ভাসিলি

যদি কিছু হয় তবে আপনার দ্বিতীয় উদাহরণটি আরও সহজ পরিস্থিতি উপস্থাপন করে: এটি কেবলমাত্র একটি তৈরি করা অবজেক্ট ব্যবহার করে withContextযেখানে 1 ম উদাহরণটি প্রথমে এটি তৈরি করে, তার মধ্যে রূপান্তরিত হয় withContextএবং তারপরে পরে পড়ে withContext। সুতরাং 1 ম উদাহরণ আরও থ্রেড সুরক্ষা বৈশিষ্ট্য অনুশীলন করে।
মার্কো টপলনিক

... এবং উভয় উদাহরণই কেবলমাত্র "প্রোগ্রামের আদেশ" এর অনুভূতিটি ঘটেছিল - এর আগে ঘটে যা সবচেয়ে তুচ্ছ। আমি এখানে কর্টাইনগুলির স্তরে কথা বলছি, অন্তর্নিহিত জেভিএম নয়। সুতরাং মূলত, আপনি জিজ্ঞাসা করছেন যে কোটলিন কর্টিনগুলি এত মারাত্মকভাবে ভেঙে গেছে যে তারা এমনকি প্রোগ্রামের অর্ডারটি প্রদান করে না - এর আগে ঘটে।
মার্কো টপোলনিক

1
@ মারকো টপলনিক, আমি ভুল হলে আমাকে সংশোধন করুন, তবে জেএলএস একই থ্রেডে মৃত্যুদন্ড কার্যকর করার জন্য "প্রোগ্রামের আদেশ হওয়ার আগেই" গ্যারান্টি দেয়। এখন, কর্টাইন সহ, কোডটি ধারাবাহিক মনে হলেও বাস্তবে এমন কিছু যন্ত্রপাতি রয়েছে যা এটিকে বিভিন্ন থ্রেডে অফলোড করে। আমি আপনার বক্তব্যটি বুঝতে পারি "এটি এমন একটি প্রাথমিক গ্যারান্টি যে এটি পরীক্ষা করার জন্য আমি আমার সময় নষ্টও করব না" (অন্য মন্তব্য থেকে), তবে আমি এই প্রশ্নটি একটি কঠোর উত্তর পেতে বলেছিলাম। আমি নিশ্চিত যে আমি যে উদাহরণগুলি লিখেছি তা থ্রেড নিরাপদ তবে আমি কেন তা বুঝতে চাই।
ভাসিলি

উত্তর:


6

আপনি যে কোডটি লিখেছেন তাতে ভাগ করে নেওয়া অবস্থায় তিনটি প্রবেশাধিকার রয়েছে:

var mutableVar = 0                        // access 1, init
withContext(Dispatchers.IO) {
    mutableVar = 1                        // access 2, write
}
System.out.println("value: $mutableVar")  // access 3, read

তিনটি অ্যাক্সেস কঠোরভাবে ক্রমানুসারে অর্ডার করা হয়েছে, যার মধ্যে কোনও চুক্তি নেই, এবং আপনি নিশ্চিত হয়ে যেতে পারেন যে কোটলিনের অবকাঠামো থ্রেড পুলের কাছে ছেড়ে দেওয়ার সময় এবং আপনার কলিং কর্টিনে ফিরে যাওয়ার সময় একটি প্রান্ত স্থাপনের আগে যত্ন নেবে IO

এখানে একটি সমতুল্য উদাহরণ যা সম্ভবত আরও দৃinc়প্রতিজ্ঞ হতে পারে:

launch(Dispatchers.Default) {
    var mutableVar = 0             // 1
    delay(1)
    mutableVar = 1                 // 2
    delay(1)
    println("value: $mutableVar")  // 3
}

যেহেতু delayএকটি স্থগিতযোগ্য ফাংশন, এবং যেহেতু আমরা Defaultথ্রেড পুলের সাহায্যে প্রেরণকারী ব্যবহার করছি , সুতরাং 1, 2 এবং 3 লাইন প্রতিটি আলাদা থ্রেডে চালিত হতে পারে। অতএব ঘটনার আগে গ্যারান্টি সম্পর্কে আপনার প্রশ্ন এই উদাহরণে সমানভাবে প্রযোজ্য। অন্যদিকে, এই ক্ষেত্রে এটি পুরোপুরি সুস্পষ্ট (আমি আশা করব) যে এই কোডটির আচরণটি ক্রমানুসারে কার্যকর করার নীতিগুলির সাথে সামঞ্জস্যপূর্ণ।


1
ধন্যবাদ। "বিশ্রামের আশ্বাস" পরে এটি আসলে সেই অংশ যা আমাকে এই প্রশ্ন জিজ্ঞাসা করতে প্রেরণা জোগায়। আমি যে দস্তাবেজগুলিতে পড়তে পারি তার কোনও লিঙ্ক আছে? বিকল্পভাবে, উত্স কোডের লিঙ্কগুলি যেখানে এটি হওয়ার আগে প্রান্তটি স্থাপন করা হয়েছে সেগুলিও খুব সাহায্য করবে (যোগ দিন, সিঙ্ক্রোনাইজেশন বা অন্য কোনও পদ্ধতিতে)।
ভাসিলি

1
এটি এমন একটি প্রাথমিক গ্যারান্টি যে আমি এটি পরীক্ষা করে আমার সময় নষ্টও করব না। ফণা নীচে নেমে boils executorService.submit()এবং সেখানে কাজের শেষ হওয়ার উপর অপেক্ষা (ক সমাপ্তির জন্য কিছু বৈশিষ্ট্যসূচক প্রক্রিয়া CompletableFutureবা কিছু অনুরূপ)। কোটলিনের কর্টাইনগুলির দৃষ্টিকোণ থেকে এখানে কোনও মিল নেই ur
মার্কো টপলনিক

1
আপনি আপনার প্রশ্নটিকে জিজ্ঞাসা করার অনুরূপ হিসাবে ভাবতে পারেন "কোনও থ্রেড স্থগিত করার পরে এবং অন্য কোরটিতে পুনরায় চালু করার আগে ওএস কি কোনও ঘটনার নিশ্চয়তা দেয়?" থ্রেডগুলি সিপিইউ কর্ডগুলি থ্রেডগুলিতে কর্টিনগুলি হয়।
মার্কো টপোলনিক

1
তোমার ব্যাখ্যার জন্য ধন্যবাদ. যাইহোক, আমি কেন এই কাজ করে তা বুঝতে এই প্রশ্নটি জিজ্ঞাসা করেছি। আমি আপনার বক্তব্যটি দেখতে পাচ্ছি, তবে, এখন পর্যন্ত এটি আমি যে কড়া উত্তর খুঁজছি তা নয়।
ভাসিলি

2
ভাল ... আমি আসলে মনে করি না যে এই থ্রেডটি কোডটি অনুক্রমিকভাবে প্রতিষ্ঠিত করেছে। এটি অবশ্যই দৃserted়ভাবে জানিয়েছে আমিও সেই প্রক্রিয়াটি দেখতে আগ্রহী যে গ্যারান্টি দেয় যে উদাহরণটি প্রত্যাশা অনুযায়ী আচরণ করবে, পারফরম্যান্সকে প্রভাবিত না করে।
জি। ব্লেক মাইকে

3

কোটলিনের কর্টাইনগুলি গ্যারান্টি দেওয়ার আগে ঘটে।

নিয়ম হল: একটি coroutine ভিতরে, কোড পূর্বে একটি স্থগিত করার ফাংশন কল করার আগে ঘটে কোড পর স্থগিত কল।

কর্টিনগুলি সম্পর্কে আপনার এমন ভাবনা উচিত যেন তারা নিয়মিত থ্রেড থাকে:

যদিও কোটলিনের কোনও কর্টিন একাধিক থ্রেডে কার্যকর করতে পারে তবে এটি ঠিক পরিবর্তনীয় অবস্থার দৃষ্টিকোণ থেকে থ্রেডের মতো। একই কর্টিনে কোনও দুটি ক্রিয়া একসাথে হতে পারে না।

সূত্র: https://proandroiddev.com/hat-is-concurrent-access-to-mutable-state-f386e5cb8292

কোড উদাহরণে ফিরে আসা। ল্যাম্বদা ফাংশন বডিগুলিতে ভারগুলি ক্যাপচার করা সেরা ধারণা নয়, বিশেষত যখন ল্যাম্বদা একটি কর্টিন হয়। ল্যাম্বডার আগের কোডটি অভ্যন্তরের কোডের আগে ঘটে না।

Https://youtrack.jetbrains.com/issue/KT-15514 দেখুন


নিয়মটি আসলে এটি হ'ল: একটি সাসপেন্ড ফাংশন কল করার আগে কোডটি ঘটে- সাসপেন্ড ফাংশনের অভ্যন্তরের কোডের আগে ঘটেছিল - স্থগিত কলের পরে কোডের আগে ঘটে । এটিকে ঘুরে দেখা যায়, "কোডের প্রোগ্রাম ক্রমটিও কোডের আগে অর্ডার হওয়ার আগে হয়" to এই বিবৃতিতে স্থগিতযোগ্য ফাংশনগুলির জন্য নির্দিষ্ট কোনও কিছুর অনুপস্থিতি নোট করুন Note
মার্কো টপোলনিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.