🚀 اتمیک در ++C — نجات دادهها در ازدحام فعالیت تردها!
وقتی در ++C با چند تا ترد همزمان کار میکنی، مراقب باش! چون اگر چند تا ترد همزمان به یه متغیر دست بزنن بدون هماهنگی، همهچی به هم میریزه. اینجاست که std::atomic به دادت میرسه.
🎯 سناریو: شمارش همزمان با تردها
در تابع()f، هر ترد داره ۱۰,۰۰۰ بار یه شمارنده رو زیاد میکنه. ولی تفاوت بزرگ اینه که acnt از نوع std::atomic_int هست، ولی cnt یه int معمولیه.
خروجی احتمالی( چون شمارنده معمولی رفتار ثابتی نداره):
چرا اینطوریه؟ چون cnt++ایمن نیست و وقتی چند تا ترد با هم بهش دست میزنن، مقدار نهایی اشتباه میشه. این یعنی Race Condition.
معنی Race Condition:
حالت Race conditionها (شرایط مسابقه) بیشتر در زمینهی علوم کامپیوتر و برنامهنویسی مطرح میشن. این مشکل زمانی به وجود میاد که دو پردازه (process) یا ترد (thread) در یک برنامهی کامپیوتری همزمان تلاش میکنن به یک منبع مشترک دسترسی پیدا کنن و این باعث بروز اختلال در سیستم میشه. Race conditionها یکی از مشکلات رایج در برنامههای چندتردی (multithreaded) به شمار میان.
🔍 تفاوت اتمیک و غیراتمیک چیه؟
هر cnt++ در واقع ۳ مرحله داره:
1_خوندن مقدار از RAM
2_اضافه کردن ۱
3_نوشتن مقدار جدید
وقتی چند تا ترد با هم این کارو انجام بدن، ممکنه دو ترد همزمان مقدار رو بخونن، هر دو ۱ اضافه کنن، و هر دو همون مقدار جدید رو ذخیره کنن — یعنی یه شمارش گم میشه!
ولی با std::atomic_int، این عملیات به صورت اتمی و همزمانیامن (Thread-Safe) انجام میشه.
بحثش مفصله. حتی میتونید از سطحهای مختلف memory_order استفاده کنید، مخصوصاً وقتی بین تردها قراره داده به اشتراک گذاشته بشه.
یه راهکار دیگه هم استفاده از std::mutex هست؛ با این روش، یک ترد بخشی از کد رو قفل میکنه و بقیه تردها تا زمانی که این قفل باز نشه، اجازه ورود به اون بخش رو ندارن.
منبع: https://en.cppreference.com/w/cpp/atomic/atomic.html
#Cpp #Threads #Atomic #RaceCondition #MultiThreading #Concurrency #برنامهنویسی #سی_پلاس_پلاس
☕️Telegram | Website | Discord
وقتی در ++C با چند تا ترد همزمان کار میکنی، مراقب باش! چون اگر چند تا ترد همزمان به یه متغیر دست بزنن بدون هماهنگی، همهچی به هم میریزه. اینجاست که std::atomic به دادت میرسه.
🎯 سناریو: شمارش همزمان با تردها
std::atomic_int acnt;
int cnt;
void f() {
for (auto n{10000}; n; --n) {
++acnt; // امن!
++cnt; // خطرناک!
}
}
int main()
{
{
std::vector<std::jthread> pool;
for (int n = 0; n < 10; ++n)
pool.emplace_back(f);
}
std::cout << "The atomic counter is " << acnt << '\n'
<< "The non-atomic counter is " << cnt << '\n';
}
در تابع()f، هر ترد داره ۱۰,۰۰۰ بار یه شمارنده رو زیاد میکنه. ولی تفاوت بزرگ اینه که acnt از نوع std::atomic_int هست، ولی cnt یه int معمولیه.
خروجی احتمالی( چون شمارنده معمولی رفتار ثابتی نداره):
The atomic counter is 100000
The non-atomic counter is 69696
چرا اینطوریه؟ چون cnt++ایمن نیست و وقتی چند تا ترد با هم بهش دست میزنن، مقدار نهایی اشتباه میشه. این یعنی Race Condition.
معنی Race Condition:
حالت Race conditionها (شرایط مسابقه) بیشتر در زمینهی علوم کامپیوتر و برنامهنویسی مطرح میشن. این مشکل زمانی به وجود میاد که دو پردازه (process) یا ترد (thread) در یک برنامهی کامپیوتری همزمان تلاش میکنن به یک منبع مشترک دسترسی پیدا کنن و این باعث بروز اختلال در سیستم میشه. Race conditionها یکی از مشکلات رایج در برنامههای چندتردی (multithreaded) به شمار میان.
🔍 تفاوت اتمیک و غیراتمیک چیه؟
هر cnt++ در واقع ۳ مرحله داره:
1_خوندن مقدار از RAM
2_اضافه کردن ۱
3_نوشتن مقدار جدید
وقتی چند تا ترد با هم این کارو انجام بدن، ممکنه دو ترد همزمان مقدار رو بخونن، هر دو ۱ اضافه کنن، و هر دو همون مقدار جدید رو ذخیره کنن — یعنی یه شمارش گم میشه!
ولی با std::atomic_int، این عملیات به صورت اتمی و همزمانیامن (Thread-Safe) انجام میشه.
بحثش مفصله. حتی میتونید از سطحهای مختلف memory_order استفاده کنید، مخصوصاً وقتی بین تردها قراره داده به اشتراک گذاشته بشه.
یه راهکار دیگه هم استفاده از std::mutex هست؛ با این روش، یک ترد بخشی از کد رو قفل میکنه و بقیه تردها تا زمانی که این قفل باز نشه، اجازه ورود به اون بخش رو ندارن.
منبع: https://en.cppreference.com/w/cpp/atomic/atomic.html
#Cpp #Threads #Atomic #RaceCondition #MultiThreading #Concurrency #برنامهنویسی #سی_پلاس_پلاس
☕️Telegram | Website | Discord
❤🔥2💔2