VISUAL C# No.42: Multi Threading dalam .NET dan C#


Pasti diantara anda banyak yang sudah familiar dengan Thread. Apa sebetulnya Thread itu? Kalo kita definisikan Thread sebagai ‘Process’, maka kurang tepat, karena ‘Process’ itu sendiri bisa memiliki 1 Thread bisa juga memiliki 2 Thread (Multi-Threading).

Thread bisa dibilang merupakan sebuah instruksi pada program. Sebuah program bisa memiliki satu Thread (“SingleThreading”) atau bisa memiliki banyak Thread (“MultiThreading”).


Mari kita mambahas Thread dan MultiThreading, saya di sini menggunakan Visual Studio 2013 Update 2, IDE tercanggih update terbaru pada saat tutorial ini ditulis.


Sebagai contoh, mari kita buka Task Manager pada komputer kita (saya menggunakan Windows 8.1 64 bit, OS Tercanggih dan Terbaru saat tutorial ini ditulis).
Lihat gambar 1:



Silahkan anda perhatikan, setiap program yang kita run setidaknya memiliki 1 Thread, bahkan banyak sekali yang ‘MultiThread’. Setiap proses setidaknya me-run 1 Thread sebagai Primary Thread, kalo dalam C# sebagai ‘Primary Thread’ nya adalah method main().

Lanjut...

Bagaimana Multi Thread bekerja?

Sebetulnya, dulu, setiap aplikasi hanya single Thread, artinya setiap program yang dibuat hanya memiliki 1 (satu) buah Thread. Sehingga setiap process eksekusi harus “berurutan”. Anda tidak bisa mengeksekusi B sebelum A selesai dieksekusi.

Inilah yang disebut dengan “berurutan”.

Tetapi sekarang berkat adanya fasilitas multiThreading, kita bisa mengeksekusi prosess secara “bersamaan”, sehingga B dan A dapat dieksekusi secara “bersamaan”, tidak “berurutan”. Dampaknya adalah proses yang dikerjakan oleh program bisa sangattt jauh lebih cepat.

Problem with Multi Thread?

Sebetulnya, multiThreading memberikan keuntungan yang sangat luar biasa. Tapi ada problem juga bila developer tidak cekatan dalam penulisan program. Mari kita renungkan ada sebuah MultiThreading yang sedang running “bersamaan” yaitu ThreadPertama dan ThreadKedua.

Kedua-duanya sama sama membaca dan menulis memory dalam variable X. Nah inilah problemnya, bayangkan bila kedua Thread sama – sama mengakses variable yang dibutuhkan *nilainya satu sama lain :)

Yuk, kita buat sebuah contoh:



Ayo perhatikan baik – baik kode di atas, yang sedang mengantuk silahkan minum kopi terlebih dahulu.
Intinya, kita membuat sebuah console application yang memiliki dua (2) buah Thread yang berjalan bersamaan. Keduanya mengakses variable yang sama yaitu ‘outputText’.

Coba tebak, bagaimana hasil dari debug kode diatas?

Kalo saya boleh menebak, saya yakin pasti banyak dari anda akan menjawab seperti ini:

Display Thread 1
Thread1 output --> Saya Thread 1

Display Thread 2
Thread1 output --> Saya Thread 2


Tapi ternyata tidak demikian, hasil dari debug kode malah menjadi sangat tidak bisa diprediksi.
Lihat gambar 2:


Lihat, hasilnya unpredictable! :(

Inilah yang dinamakan dengan ‘Race Condition’ , lalu apa solusinya? kita akan membahasnya di belakang nanti...
Ok, mari kita kembali ke ‘Thread’:)

System.Thread Namespace
Thread dalam framework .NET berada dalam System.Thread namespace. Jadi bila anda ingin bermain-main dengan Thread, maka terlebih dahulu jangan lupa untuk mengimport namespace ini pada kode anda terlebih dahulu.
Di dalam namespace ini, terdapat beberapa class yang nanti bisa kita gunakan dalam kaitannya dengan proses Thread. Class – class yang ada dalam System.Thread namespace itu diantaranya adalah sebagai berikut:

Class Thread : Class ini kita gunakan saat kita akan membuat Thread yang akan dieksekusi di dalam CLR. Kita bisa membuat beberapa thread pada application domain.

Class Mutex : Mutex merupakan kepanjangan dari “Mutual Exclusion”, yaitu nanti bisa digunakan untuk sinkronisasi antar beberapa Thread. Penggunaan Mutex akan sangat membantu sekali untuk anda yang sangat sering berhubungan dengan kerja multi thread.

Class Monitor : Class ini bisa kita gunakan untuk sinkronisasi multi thread dengan Lock dan Wait.

Class Smaphore : Class ini digunakan untuk membatasi jumlah thread yang dapat mengakses resource tertentu.

Dan Class – Class yang lain tentunya. Anda bisa melihat banyak sekali Class yang bisa kita gunakan dalam System.Threading namespace ini :)

Nah, dalam tutorial ini kita hanya membahas tentang Class Thread, itupun cuman beberapa method dari class ini saja :)

YUK, MARI KITA MEMBUAT THREAD,

Untuk membuat Thread, kita akan menggunakan Class Thread. Pada class ini ada banyak sekali properties yang bisa kita gunakan, dari sekian banyak properties, mari kita gunakan beberapa saja seperti:

CurentThread : digunakan untuk mendapatkan current Thread yang sedang running.

IsAlive : digunakan untuk mendapatkan status dari Thread yang sedang running, apakah sedang tereksekusi apa tidak, akan me-return true dan false.

IsBackground : digunakan untuk mengecheck atau men-set apakah Thread ini merupakan Thread Background atau bukan. Hasil nya adalah boolean (true atau false);

Name : digunakan untuk mendapatkan atau me-set nama untuk Thread yang sedang berjalan.

Untuk melihat properties yang lain dari Class Thread, anda bisa membukanya di Visual Studio Documentation.

Perhatikan dan amati kode sederhana berikut ini, ingat, amati dan pahami, , , yang sedang mengantuk silahkan ambil kopi terlebih dahulu.



Nah, pada kode di atas, kita membuat sebuah Thread. Kita berikan nama untuk Thread, kemudian kita meloading semua properties dari Thread tersebut ke dalam layar komputer.
Untuk pembuatan thread pun tidak harus pakai “new”, melainkan dengan Thread.currentThread;
Jika dicoba, maka hasil yang didapat dari kode di atas adalah sebagai berikut:
Lihat gambar 3:


Bisa di lihat, kita membuat Thread dengan:

Thread T = Thread.CurrentThread;
Sekarang kita akan membuat Thread dengan new:
Thread t = new Thread(myOtherThread);


Lihat gambar 4:


Pada kode di atas, kita membuat Thread dari ‘new’ dengan memanggil method class yang lain. Method yang lain ini pun bisa disebut juga dengan Thread. Sehingga dipastikan bahwa kode di atas kita sudah me-running dua buah Thread secara bersamaan, hasilnya adalah sebagai berikut:
Lihat gambar 5:


Perlu diperhatikan bahwa tidak ada garansi bahwa main thread akan selalu muncul di baris pertama. Bisa juga kedua. Seperti problem kita pada kode sebelumnya yang kita sebut dengan ‘race condition’ :)

ISSUES DALAM MULTITHREADING

Race Condition dan Lock()
Adalah keadaan dimana dua atau lebih Thread mengakses object yang sama sementara pengaksesan tersebut tidak sinkron. Contohnya adalah pada kode paling awal dari tutorial ini.
Solusi untuk ‘Race Condition’ adalah dengan mengunci (Lock) Thread terlebih dahulu.
Perhatikan kode berikut ini:



Hi, kode – kode di atas menggunakan keyword static, untuk yang belum paham penggunaan keyword static silahkan buka tutorial sebelumnya :)

Perhatikan, kita menggunakan lock() untuk mengunci thread agar tidak bisa diakses oleh kode lain.

Lock keyword bisa kita gunakan untuk menghindari race situation. Dimana sebuah thread yang sedang memproses ‘critical section’ harus dikunci supaya tidak ada thread lain yang akan mengakses ‘critical section’ ini. Bila ada thread lain yang mencoba mengakses code yang terkunci tersebut, maka thread tersebut akan wait (menunggu), hingga object yang terlock tersebut direlease.

Lalu bagaimana cara me-lock kode tersebut??

Cara terbaik untuk me-lock adalah dengan membuat ‘PRIVATE OBJECT’ atau ‘STATIC PRIVATE OBJECT’ untuk melindungi data dalam instance.

Ya, buatlah private object :) , ingat, private object.
Nah, ada beberapa trik yang salah untuk lock ini, diantaranya adalah sebagai berikut:

Lock(this){} --> jangan memakai trik ini, problem akan terjadi bila instance bisa diakses secara public.
lock (typeof (MyType)) --> jangan memakai trik ini karena masalah akan terjadi bila MyType bisa diakses secara public.
lock(“myLock”) --> jangan memakai trik ini, karena semua kode yang menggunakan string yang sama dalam proses tersebut akan terkena lock yang sama.

Lalu bagaimana cara menulis yang benar untuk locking?

Anda bisa melihat locking pada kode DI ATAS, kita membuat object untuk dilock :)
Hasil dari running kode diatas adalah seperti pada gambar berikut ini:
Lihat gambar 6:


Anda bisa lihat, dengan locking, race condition yang kita hadapi pada kode sebelumnya dapat teratasi.

Deadlocks
Menggunakan locking yang terlalu kompleks dapat menyebabkan deadlock. Coba bayangkan, puluhan Thread saling mengantri untuk ‘lock release’. Keadaan ini bisa menjadikan deadlock dan akhirnya program not responding.

Ada beberapa class lain selain Thread yang ada di Namespace System.Thread yaitu Monitor, Mutex, Semaphore dan lain – lain, semuanya mempunyai kegunaan sendiri – sendiri yang nanti akan kita bahas pada tutorial – tutorial berikutnya.
Terimakasih, mudah – mudahan bermanfaat,
Salam,


Tidak ada komentar

Diberdayakan oleh Blogger.