یکی از خصوصیات جالبی که در اکثر برنامه نویس های ایرانی دیده میشه اینه که همه چیز رو در حالت ایده آل در نظر می گیرن و به همین دلیل در نرم افزار های تولید داخل علاوه بر مسائلی مثل نادیده گرفتن شیء گرایی و… exception handling رو میشه یکی از یتیم ترین موضوعات پروسه تولید در نظر گرفت.
در طول دورانی که به عنوان مشاوردر کنار تیم ها کار میکنم به کرات دیده ام که نرم افزار دچار مشکل شده اونم به خاطر عدم پیش بینی خطاها یا موارد خاصی که در حین استفاده کاربر پیش میاد. یکی از امکانات #C که متاسفانه کمتر ازش استفاده میشه Lock کردن آبجکت هاست.
Lock چیست ؟ و چرا Lock ؟
Lock موجب اطمینان از عدم امکان استفاده تردها (Thread) از قطعه کدی می شود که در وضعیت بحرانی به سر می برد (وضعیت بحرانی تعبیر خود مایکروسافته، به عبارت دیگر کدی که باید Block بمونه تا وضعیتش مشخص شه) . Lock کردن آبجکت باعث انتظار و یا بلوکه شدن تردی که می خواهد از آن استفاده کند، تا زمان آزاد شدن آبجکت می شود.
مثال زیر موضوع رو به صورت کاملا کاربردی خواهد داد :
1: // Lock مثال
2: using System;
3: using System.Threading;
4:
5: class Account
6: {
7: private Object thisLock = new Object();
8: int balance;
9:
10: Random r = new Random();
11:
12: public Account(int initial)
13: {
14: balance = initial;
15: }
16:
17: int Withdraw(int amount)
18: {
19:
20: // این شرط هرگز برقرار نخواهد شد مگر اینکه بخش لاک فعال شود
21:
22: if (balance < 0)
23: {
24: throw new Exception("Negative Balance");
25: }
26:
27: // تاثیر لاک را در خطوط بعد خواهید دید
28:
29: lock(thisLock)
30: {
31: if (balance >= amount)
32: {
33: Console.WriteLine("Balance before Withdrawal : " + balance);
34: Console.WriteLine("Amount to Withdraw : -" + amount);
35: balance = balance - amount;
36: Console.WriteLine("Balance after Withdrawal : " + balance);
37: return amount;
38: }
39: else
40: {
41: return 0; // تراکنش رد خواهد شد
42: }
43: }
44: }
45:
46: public void DoTransactions()
47: {
48: for (int i = 0; i < 100; i++)
49: {
50: Withdraw(r.Next(1, 100));
51: }
52: }
53: }
54:
55: class Test
56: {
57: static void Main()
58: {
59: Thread[] threads = new Thread[10];
60: Account acc = new Account(1000);
61: for (int i = 0; i < 10; i++)
62: {
63: Thread t = new Thread(new ThreadStart(acc.DoTransactions));
64: threads[i] = t;
65: }
66: for (int i = 0; i < 10; i++)
67: {
68: threads[i].Start();
69: }
70: }
71: }