Ushbu maqolada .NET platformasida parallel va ko‘p oqimli (multi-threaded) dasturlash bo‘yicha muhim mavzular yoritilgan:
1. Task asosidagi parallel dasturlash (Task.Run)
Task — bu asinxron yoki parallel ishlarni bajarish uchun .NET platformasidagi eng mashhur abstraksiya.
- Asosiy oqimni (UI yoki Main thread) bloklamaslik
- Resurslardan samarali foydalanish
- Parallel hisob-kitoblar
using System;
using System.Threading.Tasks;
class Program
{
static void Main()
{
Console.WriteLine("Main boshlandi");
Task task = Task.Run(() =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Task ishlayapti: {i}");
Task.Delay(500).Wait();
}
});
task.Wait(); // task tugaguncha kutib turamiz
Console.WriteLine("Main tugadi");
}
}2. new Thread() bilan parallel dasturlash
Thread - bu past darajadagi parallel oqim yaratish usuli bo‘lib, Task'ga nisbatan ko‘proq nazorat beradi.
- Maxsus oqim sozlamalari kerak bo‘lsa
Taskyetarli bo‘lmasa
using System;
using System.Threading;
class Program
{
static void Main()
{
Thread thread = new Thread(() =>
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine($"Thread ishlayapti: {i}");
Thread.Sleep(500);
}
});
thread.Start();
thread.Join(); // Thread tugaguncha kutamiz
Console.WriteLine("Main oqimi tugadi");
}
}3. lock, Semaphore, SemaphoreSlim, Monitor, Mutex — Sinxronizatsiya vositalari
Ko‘p oqimli (multi-threaded) dasturlashda bir nechta oqim (thread) bir vaqtning o‘zida bir xil resursga murojaat qilsa, bu xatolarga yoki noto‘g‘ri hisob-kitoblarga olib keladi. Buni oldini olish uchun sinxronizatsiya vositalari qo‘llaniladi.
Quyida ularning har birining vazifasi va misoli bilan tanishasiz:
Vazifasi:
lock biror kod blokini faqat bitta oqim (thread) bajarishini ta’minlaydi. Bu eng oddiy va eng ko‘p ishlatiladigan sinxronizatsiya usulidir.
private static readonly object _lock = new object();
lock (_lock)
{
// faqat bitta thread kiradi
}class Counter
{
private int count = 0;
private object _lock = new object();
public void Increment()
{
lock (_lock)
{
count++;
Console.WriteLine($"Count: {count}");
}
}
}Vazifasi:
Semaphore bir vaqtning o‘zida N ta thread resursga kirishiga ruxsat beradi. U maxsus parallel xizmatlar (masalan, 3 ta printer) bo‘yicha ishlatiladi.
Semaphore semaphore = new Semaphore(2, 2); // 2 ta threadgacha kirishi mumkinSemaphore semaphore = new Semaphore(2, 2);
semaphore.WaitOne(); // kirishga ruxsat so‘rash
try
{
// resursdan foydalanish
}
finally
{
semaphore.Release(); // ruxsatni bo‘shatish
}Vazifasi:
SemaphoreSlim - Semaphore'ning faqat bir jarayon (process) ichida ishlaydigan, yengilroq va .NET-friendly versiyasidir. Asinxron kutish imkonini beradi.
SemaphoreSlim semaphore = new SemaphoreSlim(2);SemaphoreSlim semaphore = new SemaphoreSlim(2);
await semaphore.WaitAsync(); // asinxron kutish
try
{
// resursdan foydalanish
}
finally
{
semaphore.Release();
}Vazifasi:
Monitor ham lock kabi ishlaydi, ammo ko‘proq nazorat beradi (masalan: timeout, TryEnter). Bu vosita ko‘proq professional darajadagi boshqaruv uchun foydalidir.
Monitor.Enter(obj);
Monitor.Exit(obj);object _lock = new object();
Monitor.Enter(_lock);
try
{
// resursdan foydalanish
}
finally
{
Monitor.Exit(_lock);
}Vazifasi:
Mutex - bir nechta jarayonlar (process) bir xil resursga kirishini nazorat qilish uchun ishlatiladi. U lock va Monitor'dan farqli ravishda tizim darajasida ishlaydi.
Mutex mutex = new Mutex();Mutex mutex = new Mutex();
mutex.WaitOne(); // bloklash
try
{
// resursdan foydalanish
}
finally
{
mutex.ReleaseMutex(); // bo‘shatish
}| Vosita | Asosiy vazifasi | Asinxron | Jarayonlararo |
|---|---|---|---|
lock |
Faqat bitta thread'ga kirish ruxsati | Yo‘q | Yo‘q |
Monitor |
lock'dan ko‘ra ko‘proq nazorat (TryEnter, timeout) |
Yo‘q | Yo‘q |
Semaphore |
N ta threadgacha kirishni boshqarish | Yo‘q | Yo‘q |
SemaphoreSlim |
Engilroq va asinxron kutish | Ha | Yo‘q |
Mutex |
Processlararo resurs bloklash | Yo‘q | Ha |
4. Thread-safe Collections (Oqimga chidamli kollektsiyalar)
Oddiy List<T> yoki Dictionary<K,V> ko‘p oqimli ishlovda muammo tug‘diradi. Quyidagi kolleksiyalar oqimga chidamli hisoblanadi:
using System.Collections.Concurrent;
var dict = new ConcurrentDictionary<int, string>();
dict.TryAdd(1, "bir");
dict.TryAdd(2, "ikki");using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
BlockingCollection<int> queue = new BlockingCollection<int>();
Task.Run(() =>
{
for (int i = 0; i < 5; i++)
{
queue.Add(i);
Console.WriteLine($"Qo‘shildi: {i}");
Thread.Sleep(100);
}
queue.CompleteAdding();
});
foreach (var item in queue.GetConsumingEnumerable())
{
Console.WriteLine($"Qabul qilindi: {item}");
}| Vosita | Qachon ishlatiladi? |
|---|---|
Task.Run |
Oson va tez parallel ishlar uchun |
Thread |
Past darajadagi nazorat uchun |
lock, Monitor |
Resursni bir vaqtning o‘zida bir oqimga berish |
Semaphore |
Cheklangan kirish (masalan, 3 oqimgacha) |
Mutex |
Processlararo sinxronizatsiya |
| Thread-safe kolleksiya | Oqimlar o‘rtasida xavfsiz ma’lumot almashish |