یکی از خصوصیات جالبی که در اکثر برنامهنویسهای ایرانی دیده میشه اینه که همه چیز رو در حالت ایده آل در نظر میگیرن و به همین دلیل در نرمافزارهای تولید داخل علاوه بر مسائلی مثل نادیده گرفتن شیء گرایی و … exception handling رو میشه یکی از یتیمترین موضوعات پروسه تولید در نظر گرفت.
در طول دورانی که به عنوان مشاور در کنار تیمها کار میکنم به کرات دیدهام که نرمافزار دچار مشکل شده اونم به خاطر عدم پیش بینی خطاها یا موارد خاصی که در حین استفاده کاربر پیش میاد. یکی از امکانات #C که متأسفانه کمتر ازش استفاده میشه Lock کردن آبجکت هاست.
Lock چیست؟ و چرا Lock؟
Lock موجب اطمینان از عدم امکان استفاده تردها (Thread) از قطعه کدی میشود که در وضعیت بحرانی به سر میبرد (وضعیت بحرانی تعبیر خود مایکروسافته، به عبارت دیگر کدی که باید Block بمونه تا وضعیتش مشخص شه) . Lock کردن آبجکت باعث انتظار و یا بلوکه شدن تردی که میخواهد از آن استفاده کند، تا زمان آزاد شدن آبجکت میشود.
مثال زیر موضوع رو به صورت کاملاً کاربردی خواهد داد:
// Lock مثال
using System;
using System.Threading;
class Account {
private Object thisLock = new Object();
int balance;
Random r = new Random();
public Account(int initial) {
balance = initial;
}
int Withdraw(int amount) {
// این شرط هرگز برقرار نخواهد شد مگر اینکه بخش لاک فعال شود
if (balance < 0) {
throw new Exception("Negative Balance");
}
// تاثیر لاک را در خطوط بعد خواهید دید
lock (thisLock) {
if (balance >= amount) {
Console.WriteLine("Balance before Withdrawal : " + balance);
Console.WriteLine("Amount to Withdraw : -" + amount);
balance = balance - amount;
Console.WriteLine("Balance after Withdrawal : " + balance);
return amount;
} else {
return 0; // تراکنش رد خواهد شد
}
}
}
public void DoTransactions() {
for (int i = 0; i < 100; i++) {
Withdraw(r.Next(1, 100));
}
}
}
class Test {
static void Main() {
Thread[] threads = new Thread[10];
Account acc = new Account(1000);
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new ThreadStart(acc.DoTransactions));
threads[i] = t;
}
for (int i = 0; i < 10; i++) {
threads[i].Start();
}
}
}