ورود

View Full Version : race condition



ushuah
چهارشنبه 16 فروردین 1396, 11:27 صبح
باسلام به دوستان محترم
من توی درک موضوع race condition مشکل دارم
لفا کد زیر رو در نظر بگیرین



#include <iostream>
#include <thread>

using namespace std;


void thrdfunc(void)
{
for (int i = 0 ; i > -100 ; i--)
cout << "inside thread" << endl;
}

int main()
{
thread t1(thrdfunc);


for (int i = 0 ; i < 100 ; i++)
cout << "inside main " << endl;

t1.join();

return 0;
}

}



۱ - آیا برای تابعی که نوشته شده هم race condition اتفاق میفته؟ اگر جواب خیر هستش پس چرا وقتی برنامه رو اجرا می کنیم بعضی از جوابها با هم قاطی میشم . و اگر هم جواب مثبت هست پس برای توابع هم race condition اتفاق میفته و فقط مخصوص داده های به اشتراک گذاشته نیست.

۲ - فرض کنیم من توی تابع می خوام یکسری عملیات پشت سرهم انجام بدم که مثلا یکی از این عملیات صداکردن یک وب سرویس هست که اون هم یک تابع مجزاست . اگر قرار باشه که من برای جلوگیری از race condition از mutex وغیره استفاده کنم پس استفاده از multithread به چه دردی می خوره چون اون قسمت از کد قفل میشه تا انتهای تابع . در صورتی که من میخوام این تابع چندین بار به صورت همزمان استفاده بشه .

اگر ممکنه دوستان منو راهنمایی کنن
با تشکر

Felony
پنج شنبه 17 فروردین 1396, 13:07 عصر
اول تعریف Racecondition به زبان ساده :


A race condition is an undesirable situation that occurs when a device (http://whatis.techtarget.com/definition/device) or system (http://searchwindowsserver.techtarget.com/definition/system) attempts to perform two or more operations at the same time, but because of the nature of the device or system, the operations must be done in the proper sequence to be done correctly.




۱ - آیا برای تابعی که نوشته شده هم race condition اتفاق میفته؟ اگر جواب خیر هستش پس چرا وقتی برنامه رو اجرا می کنیم بعضی از جوابها با هم قاطی میشم . و اگر هم جواب مثبت هست پس برای توابع هم race condition اتفاق میفته و فقط مخصوص داده های به اشتراک گذاشته نیست.
بله اتفاق میافته چون پیاده سازی buffer مربوط به cout قبلا thread safe نبوده و در نسخه های جدید هم من چیزی در مورد treade safe بودنش ندیدم ، این پیاده سازی مشکل محسوب نمیشه همونطور که در WinForm API هیچ تردی حق نداره مستقیم با UI در ارتباط باشه جر Main Thread و باقی تردها وظیفه دارن درخواست تغیرات در UI رو با Main Thread سینک کنن تا اون براشون انجام بده .


۲ - فرض کنیم من توی تابع می خوام یکسری عملیات پشت سرهم انجام بدم که مثلا یکی از این عملیات صداکردن یک وب سرویس هست که اون هم یک تابع مجزاست . اگر قرار باشه که من برای جلوگیری از race condition از mutex وغیره استفاده کنم پس استفاده از multithread به چه دردی می خوره چون اون قسمت از کد قفل میشه تا انتهای تابع . در صورتی که من میخوام این تابع چندین بار به صورت همزمان استفاده بشه .
مفهموم ترد این نیست که همه چیز رو بنداز تو ترد تا با هم انجام بشه ، برای صدا زدن وب سرویس بلاخره باید منتظر جوابش بمونی تا بعد از رسیدن پاسخ عملیاتی انجام بدی ( مثلا دیتا برگشتی از وب سرویس رو پارز کنی )

در کل وقتی منبع اشتراکی شما Threadsafe باشه نگرانیدر مورد استفاده اشتراکیش نخواهد بود ، عملیات های IO مشکلات Thread safe نبودن رو دارن و باید با راهکارهایی مثل mutex ، semaphore و ... حلشون کرد .

ushuah
پنج شنبه 17 فروردین 1396, 20:00 عصر
متشکرم از جواب شما .

اما اینجا یک اتفاقی میفته فرض کنین که ما قبل از دستور for از یک lock mutex و بعد از بسته شدن دستور for یک unlock mutex بزاریم بعد از اینکه برنامه رو اجرا می کنیم میبینیم که یکی از for ها بطور کامل اجرا میشه و بعداز اینکه تموم شد اون یکی for به صورت کامل اجرا میشه . که این اصلا با ذات multithread برابر نیست خوب اگه قرار باشه این اتفاق بیفته که دیگه multithread مفهوم نداره


میشه لطفا توضیح بدین در این مورد

Felony
جمعه 18 فروردین 1396, 07:22 صبح
این ذات مالتی ترد رو کی بهتون اینطوری گفته ؟
پست قبل توضیح دادم ، منبعی که برای مالتی ترد استفاده میشه باید Thread Safe باشه .
مشکل cout هست که thread safe نیست و شما دارید تو تردهای مجزا ازش استفاده میکنید و بهتون گفتم اکثرا این مشکل تو IO دیده میشه و برای ساختار ها و دیتا استراکچرهای دیگه پیاده سازی های thread safe شون اکثرا قابل دسترس هست .
مثلا در ویندوز فقط ترد اصلی برنامه حق داره UI برنامه رو به روزرسانی کنه و تردهای دیگه حق ندارن به صورت مستقیم UI رو دستکاری کنن و برای اعمال تغییرات در UI باید درخواستشون تو Context ترد اصلی انجام بشه .


اما اینجا یک اتفاقی میفته فرض کنین که ما قبل از دستور for از یک lock mutex و بعد از بسته شدن دستور for یک unlock mutex بزاریم بعد از اینکه برنامه رو اجرا می کنیم میبینیم که یکی از for ها بطور کامل اجرا میشه و بعداز اینکه تموم شد اون یکی for به صورت کامل اجرا میشه . که این اصلا با ذات multithread برابر نیست خوب اگه قرار باشه این اتفاق بیفته که دیگه multithread مفهوم نداره
طبیعیه ، با کدی که نوشتید Thread Safe نبودن cout رو اینطور مدیریت کردید .
به عنوان تست این بار داخل حلقه ها قبل از cout میوتکس رو ست کنید و بعد از چاپ میتوکس رو آزاد کنید .

m.r226
پنج شنبه 31 فروردین 1396, 12:30 عصر
همونطور که بقیه دوستان گفتن شرایط رقابتی اتفاق میفته، دلیلشم گفتن

بهتره برای موتکس از این استفاده کنی :
std::scoped_lock (http://en.cppreference.com/w/cpp/thread/scoped_lock)

یا از این که نیاز داره boost رو نصب کنی :
boost::mutex::scoped_lock