مطالب
React 16x - قسمت 2 - بررسی پیشنیازهای جاوا اسکریپتی - بخش 1
برای کار با React، نیاز است با ES6 آشنایی داشته باشید که در این سایت، یک سری کامل بررسی مقدمات آن‌را پیشتر مرور کرده‌ایم. علاوه بر توصیه‌ی مطالعه‌ی این سری (اینکار الزامی است)، در این قسمت خلاصه‌ی بسیار سریع و کاربردی آن‌را که بیشتر در برنامه‌های مبتنی بر React مورد استفاده قرار می‌گیرند، با هم مرور خواهیم کرد. در قسمت‌های بعدی، اهمیت ذکر این خلاصه بیشتر مشخص می‌شود.

برای بررسی ویژگی‌های جاوا اسکریپت مدرن، یک پروژه‌ی جدید React را ایجاد می‌کنیم.
> create-react-app sample-02
> cd sample-02
> npm start
سپس تمام کدهای داخل index.js را نیز حذف می‌کنیم. اکنون تمام کدهای خالص جاوا اسکریپتی خود را داخل این فایل خواهیم نوشت.
به علاوه چون در این قسمت خروجی UI نخواهیم داشت، تمام خروجی را در کنسول developer tools مرورگر خود می‌توانید مشاهده کنید (فشردن دکمه‌ی F12).


var، let و const

در اکثر زبان‌های برنامه نویسی، متغیرها در محدوده‌ی دید قطعه کدی که تعریف شده‌اند (scope)، قابل دسترسی هستند. برای نمونه محتوای فایل index.js پروژه را به صورت زیر تغییر داده و با فرض اجرای دستور npm start، خروجی آن‌را می‌توان در کنسول مرورگر مشاهده کرد.
function sayHello() {
  for (var i = 0; i < 5; i++) {
    console.log(i);
  }
  console.log(i);
}

sayHello();
در این مثال متغیر i، مخصوص قطعه کد حلقه، تعریف شده‌است. بنابراین به ظاهر نباید خارج از این حلقه نیز قابل دسترسی باشد. اما خروجی آن به صورت زیر است:


در آخرین پیمایش حلقه، i مساوی 5 شده و از حلقه خارج می‌شود. اما چون در اینجا برای تعریف متغیر از واژه‌ی کلیدی var استفاده شده‌است، محدوده‌ی دید آن به کل تابعی که در آن تعریف شده‌است، بسط پیدا می‌کند. به همین جهت در این خروجی، عدد 5 را نیز مشاهده می‌کند که حاصل دسترسی به i، خارج از حلقه‌است.
برای یک دست سازی این رفتار با سایر زبان‌های برنامه نویسی، در ES6، واژه‌ی کلیدی جدیدی به نام let تعریف شده‌است که میدان دید متغیر را به قطعه کدی که در آن تعریف شده‌است، محدود می‌کند. اکنون اگر در حلقه‌ی فوق بجای var از let استفاده شود، یک چنین خطایی در مرورگر ظاهر خواهد شد که عنوان می‌کند، i استفاده شده‌ی در خارج از حلقه، تعریف نشده‌است.
./src/index.js
  Line 14:15:  'i' is not defined  no-undef

Search for the keywords to learn more about each error.

علاوه بر let، واژه‌ی کلیدی جدید const نیز به ES6 اضافه شده‌است که از آن برای تعریف ثوابت استفاده می‌شود. constها نیز همانند let، میدان دید محدود شده‌ای به قطعه کد تعریف شده‌ی در آن دارند؛ اما قابلیت انتساب مجدد را ندارند:
 const x = 1;
x = 2; // Attempting to override 'x' which is a constant.
اگر یک چنین قطعه کدی را اجرا کنیم، خطای x is const را در مرورگر می‌توان مشاهده کرد.

به صورت خلاصه از این پس واژه‌ی کلیدی var را فراموش کنید. همیشه با const جهت تعریف متغیرها شروع کنید. اگر به خطا برخوردید و نیاز به انتساب مجدد وجود داشت، آن‌را به let تغییر دهید. بنابراین استفاده از const همیشه نسبت به let ارجحیت دارد.


اشیاء در جاوا اسکریپت

اشیاء در جاوا اسکریپت به صورت مجموعه‌ای از key/value‌ها تعریف می‌شوند:
const person = {
  name: "User 1",
  walk: function() {}, // method
  talk() {} // concise method
};
در اینجا امکان تعریف یک تابع نیز وجود دارد که چون درون یک شیء قرار می‌گیرد، اینبار «متد» نامیده می‌شود. همچنین در ES6 می‌توان این متدها را به صورت معمولی، مانند متد talk نیز تعریف کرد که به آن‌ها concise method می‌گویند. بنابراین نحوه‌ی تعریف فوق را به نحو زیر نیز می‌توان خلاصه کرد:
const person = {
  name: "User 1",
  walk() {},
  talk() {}
};
پس از تعریف این شیء، روش دسترسی به اجزای آن به صورت زیر است:
person.talk();
person.name = "User 3";
person["name"] = "User 2";
به دو مورد اول، روش dot notation می‌گویند که از همان ابتدا دقیقا مشخص است کدامیک از خواص و متدهای شیء تعریف شده، مورد استفاده قرار می‌گیرند.
مورد آخر همان روش استفاده از key/valueها است که اساس اشیاء جاوا اسکریپتی را تشکیل می‌دهد. البته از این روش فقط زمانی استفاده کنید که قرار است یکسری کار پویا صورت گیرند (مقدار key به صورت متغیر دریافت شود) و از ابتدا مشخص نیست که کدام خاصیت یا متد قرار است تعریف و استفاده شود:
const targetMember = "name";
person[targetMember] = "User 2";


واژه‌ی کلیدی this در جاوا اسکریپت

از واژه‌ی کلیدی this، در قسمت‌های بعدی زیاد استفاده خواهیم کرد. به همین جهت نیاز است تفاوت‌های اساسی آن‌را با سایر زبان‌های برنامه نویسی بررسی کنیم.
همان شیء person را که پیشتر تعریف کردیم درنظر بگیرید. در متد walk آن، مقدار this را لاگ می‌کنیم:
const person = {
  name: "User 1",
  walk() {
    console.log(this);
  },
  talk() {}
};

person.walk();
خروجی این قطعه، به صورت زیر است:


شیء this در جاوا اسکریپت، همانند سایر زبان‌های برنامه نویسی مانند سی‌شارپ و یا جاوا رفتار نمی‌کند. در سایر زبان‌های نامبرده شده، this همواره ارجاعی را به وهله‌ای از شیء جاری، باز می‌گرداند؛ دقیقا همانند تصویری که در بالا مشاهده می‌کنید. در اینجا نیز this جاوا اسکریپتی لاگ شده، ارجاعی را به وهله‌ی جاری شیء person، بازگشت داده‌است. اما مشکل اینجا است که this در جاوا اسکریپت، همیشه به این صورت رفتار نمی‌کند!
برای نمونه در ادامه یک ثابت را به نام walk تعریف کرده و آن‌را به person.walk مقدار دهی می‌کنیم:
const walk = person.walk;
console.log(walk);
دقت داشته باشید که در اینجا از () استفاده نشده‌است (متد walk اجرا نشده‌است). یعنی صرفا «ارجاعی» از متد walk شیء person را به ثابت walk نسبت داده‌ایم. بنابراین اکنون ثابت walk نیز یک function است که حاصل console.log آن به صورت زیر است:


سؤال: اکنون اگر این function را با فراخوانی ()walk اجرا کنیم، چه خروجی را می‌توان مشاهده کرد؟


اینبار this لاگ شده، به شیء person اشاره نمی‌کند و شیء استاندارد window مرورگر را بازگشت داده‌است!
اگر یک function به صورت متدی از یک شیء فراخوانی شود، مقدار this همواره اشاره‌گری به وهله‌ای از آن شیء خواهد بود. اما اگر این تابع به صورت متکی به خود و به صورت یک function و نه متد یک شیء، فراخوانی شود، اینبار this، شیء سراسری جاوا اسکریپت یا همان شیء window را بازگشت می‌دهد.

یک نکته: اگر strict mode جاوا اسکریپت را در پروژه‌ی جاری فعال کنیم، بجای شیء window، مقدار undefined را در خروجی فوق شاهد خواهیم بود.


اتصال مجدد this به شیء اصلی در جاوا اسکریپت

تا اینجا دریافتیم که اگر یک function را به صورت متکی به خود و نه جزئی از یک شیء فراخوانی کنیم، شیء this در این حالت به شیء window سراسری مرورگر اشاره می‌کند و اگر strict mode فعال باشد، فقط undefined را بازگشت می‌هد. اکنون می‌خواهیم بررسی کنیم که چگونه می‌توان این مشکل را برطرف کرد؛ یعنی صرف‌نظر از نحوه‌ی فراخوانی متدها یا تابع‌ها، this همواره ارجاعی را به شیء person بازگشت دهد.
در جاوا اسکریپت، تابع‌ها نیز شیء هستند. برای مثال person.walk نوشته شده نیز یک شیء است. برای اثبات ساده‌ی آن فقط یک دات را پس از person.walk قرار دهید:


همانطور که مشاهده می‌کنید، شیء person.walk مانند تمام اشیاء دیگر جاوا اسکریپت، به همراه متد bind نیز هست. کار آن، انقیاد یک تابع، به یک شیء است. یعنی هرچیزی را که به عنوان آرگومان آن، به آن ارسال کنیم، به عنوان مقدار شیء this درنظر می‌گیرد:
const walk2 = person.walk.bind(person);
console.log(walk2);
walk2();
در اینجا متد bind، یک وهله‌ی جدید از person.walk را بازگشت می‌دهد که در آن شیء person را به عنوان شیء this، تنظیم کرده‌است. به همین جهت اینبار فراخوانی walk2 که به شیء person متصل شده‌است، به this صحیحی بجای window سراسری اشاره می‌کند. از این روش در برنامه‌های مبتنی بر React زیاد استفاده می‌شود.


Arrow functions

تابع زیر را درنظر بگیرید که به یک ثابت انتساب داده شده‌است:
const square = function(number) {
  return number * number;
};
در ES6، روش ساده‌تر و تمیزتری برای این نوع تعاریف، ذیل ویژگی جدید Arrow functions اضافه شده‌است. برای تبدیل قطعه کد فوق به یک arrow function، ابتدا واژه‌ی کلیدی function را حذف می‌کنیم. سپس بین پارامتر تابع و {}، یک علامت <= (که به آن fat arrow هم می‌گویند!) قرار می‌دهیم:
const square2 = (number) => {
  return number * number;
};
اگر مانند اینجا تنها یک تک پارامتر وجود داشته باشد، می‌توان پرانتزهای ذکر شده را نیز حذف کرد:
const square2 = number => {
  return number * number;
};
و اگر این متد پارامتری نداشت، از () استفاده می‌شود.
در ادامه اگر بدنه‌ی این تابع، فقط حاوی یک return بود، می‌توان آن‌را به صورت زیر نیز خلاصه کرد (در اینجا {} به همراه واژه‌ی کلیدی return حذف می‌شوند):
const square3 = number => number * number;
console.log(square3(5));
این یک سطر ساده شده، دقیقا معادل اولین const square ای است که نوشتیم. نحوه‌ی فراخوانی آن نیز مانند قبل است.

اکنون مثال مفید دیگری را در مورد Arrow functions بررسی می‌کنیم که بیشتر شبیه به عبارات LINQ در #C است:
const jobs = [
  { id: 1, isActive: true },
  { id: 2, isActive: true },
  { id: 3, isActive: true },
  { id: 4, isActive: true },
  { id: 5, isActive: false }
];
در اینجا آرایه‌ای از اشیاء job را مشاهده می‌کنید که مورد آخر آن، فعال نیست. اکنون می‌خواهیم لیست کارهای فعال را گزارشگیری کنیم:
var activeJobs = jobs.filter(function(job) {
  return job.isActive;
});
متد filter در جاوا اسکریپت، بر روی تک تک عناصر آرایه‌ی jobs حرکت می‌کند. سپس هر job را به پارامتر متد ارسالی آن که predicate نام دارد، جهت دریافت یک خروجی true و یا false، ارائه می‌دهد. اگر خروجی این متد true باشد، آن job انتخاب خواهد شد و در لیست نهایی گزارش، ظاهر می‌شود.
در ادامه می‌توان این تابع را توسط arrow functions به صورت ساده‌تر زیر نیز نوشت:
var activeJobs2 = jobs.filter(job => job.isActive);
ابتدا واژه‌ی کلیدی function را حذف می‌کنیم. سپس چون یک تک پارامتر را دریافت می‌کند، نیازی به ذکر پرانتزهای آن نیز نیست. در ادامه چون یک تک return را داریم، { return }  را با یک <= جایگزین خواهیم کرد. در اینجا نیازی به ذکر سمی‌کالن انتهای return هم نیست. نوشتن یک چنین کدی تمیزتر و خواندن آن، ساده‌تر است.


ارتباط بین arrow functions و شیء this

نکته‌ی مهمی را که باید در مورد arrow functions دانست این است که شیء this را rebind نمی‌کنند (rebind: مقدار دهی مجدد؛ ریست کردن).
در مثال زیر، ابتدا شیء user با متد talk که در آن شیء this، لاگ شده، ایجاد شده و سپس این متد فراخوانی گردیده‌است:
const user = {
  name: "User 1",
  talk() {
    console.log(this);
  }
};
user.talk();
همانطور که انتظار می‌رود، this ای که در اینجا لاگ می‌شود، دقیقا ارجاعی را به وهله‌ی جاری شیء user دارد.
اکنون اگر متد لاگ کردن را داخل یک تایمر قرار دهیم چه اتفاقی رخ می‌دهد؟
const user = {
  name: "User 1",
  talk() {
    setTimeout(function() {
      console.log(this);
    }, 1000);
  }
};
user.talk();
متد setTimeout، متدی را که به عنوان آرگومان اول آن دریافت کرده، پس از 1 ثانیه اجرا می‌کند.
در این حالت خروجی console.log، مجددا همان شیء سراسری window مرورگر است و دیگر به وهله‌ی جاری شیء user اشاره نمی‌کند. علت اینجا است که پارامتر اول متد setTimeout که یک callback function نام دارد، جزئی از هیچ شیءای نیست. بنابراین دیگر مانند فراخوانی متد ()user.talk در مثال قبلی کار نمی‌کند؛ چون متکی به خود است. هر زمان که یک متد متکی به خود غیر وابسته‌ی به یک شیء را اجرا کنیم، به صورت پیش‌فرض this آن، به شیء window مرورگر اشاره می‌کند.

سؤال: چگونه می‌توان درون یک callback function متکی به خود، به this همان شیء user جاری دسترسی یافت؟
یک روش حل این مساله، ذخیره this شیء user در یک متغیر و سپس ارسال آن به متد متکی به خود setTimeout است:
const user2 = {
  name: "User 2",
  talk() {
    var self = this;
    setTimeout(function() {
      console.log(self);
    }, 1000);
  }
};
user2.talk();
این روشی است که سال‌ها است وجود دارد؛ با ارائه‌ی arrow functions، دیگر نیازی به اینکار نیست و می‌توان از روش زیر استفاده کرد:
const user3 = {
  name: "User 3",
  talk() {
    setTimeout(() => console.log(this), 1000);
  }
};
user3.talk();
در اینجا callback function را تبدیل به یک arrow function کرده‌ایم و چون arrow functions شیء this را rebind نمی‌کنند، یعنی شیء this را به ارث می‌برند. بنابراین console.log مثال فوق، دقیقا به this شیء user اشاره می‌کند و دوباره آن‌را مقدار دهی مجدد نمی‌کند و از همان نمونه‌ی موجود قطعه کد تعریف شده، استفاده خواهد کرد.


کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: sample-02.zip

در قسمت بعد نیز بررسی پیشنیازهای جاوا اسکریپتی شروع به کار با React را ادامه خواهیم داد.
نظرات مطالب
ارسال فایل و تصویر به همراه داده‌های دیگر از طریق jQuery Ajax
developer tools مرورگر رو باز کن. برگه‌ی network اون رو برای مشاهده‌ی خروجی واقعی بررسی کن (امکان مشاهده‌ی محتوای کامل response در این برگه وجود داره). شاید خطایی دریافت کردی.
نظرات مطالب
ASP.NET MVC #21
اینجا کار می‌کنه: (با استفاده از فایرباگ بررسی کنید آیا خطایی در ارسال هست یا خیر. برگه network آن؛ همچنین JSON.stringify از IE8 به بعد به صورت توکار وجود دارد و از فایرفاکس 3.1 به بعد)

پاسخ به بازخورد‌های پروژه‌ها
ساختار گزارش خاص
این گزارش شبیه به مثال تولید برگه سؤالات امتحانی است. دو روش برای حل آن وجود دارد:
الف) استفاده از قالب سفارشی سلول‌ها: (^)
ب) استفاده از قالب‌های open office و ترکیب آن با PdfReport: (^)
نظرات مطالب
مروری بر تاریخچه محدودیت حافظه مصرفی برنامه‌های ASP.NET در IIS
- سرور 32 بیتی نمی‌تونه از حداکثر میزان RAM سرور شما (بیشتر از 2GB) نهایت استفاده رو انجام بده.  تمهیداتی هم در این زمینه هست ولی ... بهتره به یک سرور 64 بیتی کوچ کنید. بدون این تمهیدات، میزان حافظه مهیای جهت یک پروسه 32 بیتی به اندازه address space آن یعنی 2GB محدود است.
- همچنین باید کش کردن اطلاعات رو فعال کنید و اجازه بدید IIS بجای برنامه این مسایل رو راسا مدیریت کنه؛ یا از یک کش سرور مجزا استفاده کنید.
نظرات اشتراک‌ها
چندین جایگزین برای Google Reader!
مقداری زمان برای بهینه کردن feedly صرف کردم، گفتم بد نیست با شما به اشتراک بزارم.
1- اول از همه feedly باید ظاهرش جوری باشه که چشم اذیت نشه : feedly-moon-phase (برای استفاده ازاین Style باید ابتدا افزونه Stylish رو روی مرورگر نصب کنید)
2- برای استفاده بهینه از فضای صفحه نمایش برای نمایش feedها: feedly-cleaner ( بازهم Stylish باید نصب باشه)
3- یکی از ملزومات هر feed reader ای نمایش تعداد فید‌های خوانده نشده هست. متاسفانه feedly این قابلیت رو فعلآ نداره برای همین باید از اسکریپت کمکی استفاده کنیم: Feedly-Unread-Count (برای استفاده از این اسکریپت باید ابتدا افزونه Greasemonkey(فایرفاکس) یا Tampermonkey(کروم) رو نصب کنید.
4- در آخر هم برای رهایی از شر تبلیغات مزاحم که adblock(به طور پیشفرض) قادر به مهارشون نیست باید از اسکریپت کمکی دیگری استفاده کنیم:Feedly-Disable-Advertisements (افزونه reasemonkey(فایرفاکس) یاTampermonkey(کروم) باید نصب باشد)
پ.ن:
در مورد فونت  بهتر با سلیقه خودتون یکی از Style‌ها رو تغییر بدید.(معمولا Tahoma خوبه)
برای پیدا کردن هر کدوم از از افزونه‌ها کافی هست اسمش رو در گوگل جستجو کنید.

مطالب
چند نکته کوتاه و عمومی در مورد قبل و بعد از نصب ویندوز 7

- فایل ISO ایی که از سایت‌های این دور و اطراف قابل دریافت است، یک DVD از نوع bootable به شما ارائه نخواهد داد. بنابراین نیاز است تا این قابلیت را فراهم کرد. خود مایکروسافت برنامه سورس بازی را در آدرس زیر جهت تهیه یک bootable DVD یا حتی bootable flash drive از روی فایل ISO دریافت شده ارائه داده است:


- نیاز است تا کلیه افزونه‌ها، کلمات عبور ذخیره شده و غیره‌ی فایرفاکس را بتوان به سیستم جدید انتقال داد. ابزار رایگان و سورس باز MozBackup این‌کار را به بهترین نحو ممکن میسر می‌سازد: +

- پس از نصب، نیاز به صفحه کلید فارسی مرغوب می‌باشد : + و +

- پس از نصب ویندوز 7 ، درایو ویندوز قبلی موجود شما ناپدید شده است! نحوه‌ی رفع مشکل : +

- هر چند در پیدا کردن درایورها از اینترنت مشکلی ندارد، اما بد نیست یکبار هم سیستم را با ابزار رایگانی جهت به روز بودن درایورها بررسی کرد: +

- اگر هنگام کار با Virtual PC مایکروسافت هنگام اتصال به VPN با خطای 721 متوقف شدید، نگران نباشید. با انتخاب گزینه‌ی run as admin این مشکل برطرف می‌شود.

- تنظیم DNS جدید گوگل نیز توصیه می‌شود: +

و یک گجت تقویم فارسی هم کفایت می‌کند : + و یا +

مطالب
برنامه نویسی موازی - بخش اول - مفاهیم

برنامه نویسی موازی، نقطه‌ی متقابل برنامه نویسی سریال که حتی گاها با برنامه نویسی سریال به سبک Asynchronous به اشتباه گرفته می‌شود، به سبکی از برنامه نویسی گفته می‌شود که در آن برنامه نویس قابلیت اجرای بخش‌های موازی برنامه را از طریق چندین Thread و به طور همزمان ایجاد کرده باشد. نکاتی که در این سبک برنامه نویسی بسیار مهم است، مهارت‌های برنامه نویس در درک قسمت‌های موازی برنامه و مجزا سازی این بخش‌ها از یکدیگر است تا کمترین ارتباط را با هم داشته باشند. مشخصا تمامی یک برنامه قابلیت موازی سازی را نخواهد داشت؛ اما مفهومی به عنوان درجه‌ی موازی سازی در هر برنامه وجود دارد که ایده آل موازی سازی، رسیدن به این درجه‌ی از موازی سازی است.
در برنامه نویسی موازی، قسمت‌هایی از برنامه که به Thread‌های مجزایی برای اجرا محول شده‌اند، می‌توانند تقریبا در یک زمان شروع به اجرا کنند و اینگونه است که سرعت اجرای عملیات افزایش پیدا می‌کند. به عنوان مثال فرض کنید برنامه‌ای داریم که ۱۰۰ رکورد از پایگاه داده واکشی می‌کند و بررسی‌ای بر روی یکی از فیلدهای آن انجام می‌دهد که ۳ ثانیه زمان گیر است و در صورت وجود شرایط خاصی، آن رکورد را لاگ می‌کند. در برنامه نویسی سریال، برسی ۱۰۰ رکورد، به ۳۰۰ ثانیه زمان برای انجام احتیاج دارد؛ ولی با فرض انجام همین عملیات با دو Thread به صورت موازی، این زمان تقریبا به نصف کاهش پیدا خوهد کرد.


چرا و در چه زمانی باید به سراغ برنامه نویسی موازی رفت !؟


نرم افزارهای بزرگ با تعداد تراکنش‌های بالا و حجم اطلاعات بالا که همواره نیازمند پردازش مستمر هستند، لزوم استفاده‌ی بهینه از قدرت پردازشی پردازنده‌ها را ایجاب می‌کنند. به طور کل می‌توان گفت قسمت‌هایی از برنامه که عملیات پردازشی را روی داده‌های مجزا انجام می‌دهند، بهترین بخش برای انجام عملیات به صورت موازی و همزمان هستند. البته نباید این نکته را نیز فراموش کرد که عملیات ایجاد Thread و مدیریت آن‌ها، دارای سربار است. ازین‌رو بهتر است برای کارهای ساده و کوچک، به سراغ برنامه نویسی موازی نرفت.


در اجرای موازی بخش‌های مختلف برنامه، ترتیب انجام هر بخش نباید در نتیجه‌ی کلی تاثیر گذار باشد. در عملیات جمع یک مجموعه می‌توان آن را به چند Thread مجزا محول کرد تا هر بخش از مجموعه را یک Thread جمع بزند و در نهایت نتیجه‌ی کل Thread‌ها با هم جمع شود. در این عملیات ترتیب اتمام کار هر Thread، نتیجه‌ای بر Thread‌های دیگر و نتیجه‌ی نهایی، نخواهد داشت. اما در شکل بالا بعد از اتمام انجام عملیات تبدیل حروف کوچک به بزرگ توسط هر Thread، گارانتی‌ای برای چاپ آنها به همان ترتیبی که از سورس خوانده شده‌اند، وجود ندارد. به عبارتی ممکن است در ابتدا وظیفه‌ی 2 Thread تمام شده باشد و بعد 1 Thread که باعث خواهد شد در خروجی، ابتدا کاراکترهای "CD" و سپس "AB"  نمایش داده شود. البته این یک مثال ساده برای درک موضوع است.


مفهوم Thread Safe

Thread Safe یک مفهوم مرتبط به زبان‌های برنامه نویسی با قابلیت اجرای چند ریسمانی می‌باشد؛ بدین مفهوم که Thread safe فقط در نرم افزارهایی که به صورت Multi Thread نوشته شده‌اند معنا پیدا می‌کند.
درک مفهوم Thread Safe و تکنیک‌های مرتبط با آن، در نرم افزار‌های چند ریسمانی بسیار حائز اهمیت می‌باشد. چرا که باعث بروز برخی خطاهای منطقی در عملکرد سیستم خواهد شد که بعضاً ردگیری آن‌ها نیز بسیار دشوار است. به طور کلی هنگامیکه thread‌‌های مختلفی در یک برنامه در حال کار همزمان می‌باشند، رخ دادن دو اتفاق شایع زیر دور از ذهن نیست:


1- Dead Lock

مفهوم بن بست در علوم کامپیوتر، یکی ار رایج‌ترین مفاهیم است که از سطح سیستم عامل تا سیستم‌های توزیع شده، تعمیم داده می‌شود. Dead Lock  زمانی رخ می‌دهد که Thread‌های مختلف، با منابع مشترکی کار می‌کنند. بدین صورت که Thread شماره ۱، منبع A را در اختیار دارد و منتظر منبع B است. همزمان Thread شماره دو، منبع B را در اختیار دارد و منتظر منبع A است. به این شرایط، بن بست می‌گویند. شبیه سازی این اتفاق را در کد #C زیر می‌توانید ببینید:
public static void Function_A()
{
 lock (resource_1)
 {
   Thread.Sleep(1000);
   lock (resource_ 2)
   {
   }
 }
}

public static void Function_B()
{
 lock (resource_2)
 {
   Thread.Sleep(1000);
   lock (resource_1)
   {
   }
 }
}

static void Main()
{
  Thread thread_A = new Thread((ThreadStart)Function_A);
  Thread thread_B = new Thread((ThreadStart)Function_B);

  thread_A.Start();
  thread_B.Start();

  while (true)
  {
   // Stare at the two threads in deadlock.
  }
}

2- Race conditions

زمانی رخ می‌دهد که دو یا چند thread به یک مقدار مشترک دسترسی داشته باشند و تلاش کنند که در یک زمان، مقدار آن را تغییر دهند. مشکل از جایی رخ می‌دهد که شما به عنوان یک برنامه نویس نمی‌دانید، در یک زمان یکسان، برای تغییر یه مقدار مشترک بین thread‌ها، اولویت با کدام thread است. این اولویت بندی و جابجایی بین threadها وظیفه‌ی الگوریتم زمان بندی thread‌ها است که در هر زمان می‌تواند بین thread‌های مختلف سوییچ کند. این اولویت بندی می‌تواند روی عملکرد کد شما تاثیر گذار باشد؛ مخصوصا در بخش‌هایی که مقدار مشترکی برسی می‌شوند؛ مانند مثال زیر:
if (x == 5) 
{
   y = x * 2; 
}

اگر بلافاصله بعد از بررسی مقدار متغیر x توسط یک thread ،thread دیگری این مقدار را تغییر دهد، دیگر نتیجه‌ی این بلاک کد، منطقی نخواهد بود و جواب، ۱۰ نخواهد شد.

با توجه به مفاهیم عنوان شده، بررسی Thread safe بودن یک کد، با معیارهای زیر انجام می‌شود:
۱- قفل گذاری روی منابع باید به شکلی باشد که باعث بروز Dead Lock نشود.
۲- استفاده از مقادیر مشترک باید به گونه‌ای باشد که منجر به Race-conditions نشود.

حال اگر در هر برنامه، مقادیر مشترکی بین thread‌‌ها وجود داشته باشد، چه از نوع struct, class, static و ...  باید به این نکته توجه کرد که ذاتا این مقادیر Thread Safe هستند یا نه !؟ در بخش بعدی، راهکارهای قفل گذاری را برای استفاده از مقادیری که ذاتا thread safe نیستند، بررسی می‌کنیم.