පළමුව, ඔබ භාෂා නීති .යෙකු මෙන් සිතීමට ඉගෙන ගත යුතුය.
C ++ පිරිවිතර කිසිදු විශේෂිත සම්පාදකයෙකු, මෙහෙයුම් පද්ධතියක් හෝ CPU එකක් ගැන සඳහන් නොකරයි. එය සත්ය පද්ධති සාමාන්යකරණය කිරීමක් වන වියුක්ත යන්ත්රයක් ගැන සඳහන් කරයි . භාෂා නීති yer ලෝකයේ, ක්රමලේඛකයාගේ කාර්යය වන්නේ වියුක්ත යන්ත්රය සඳහා කේත ලිවීමයි; සම්පාදකයාගේ කාර්යය වන්නේ එම කේතය කොන්ක්රීට් යන්ත්රයක සත්යකරණය කිරීමයි. පිරිවිතරයට තදින් කේත කිරීමෙන්, අද හෝ අවුරුදු 50 ක් වුවද, අනුකූල C ++ සම්පාදකයෙකු සහිත ඕනෑම පද්ධතියක වෙනස් කිරීමකින් තොරව ඔබේ කේතය සම්පාදනය කර ක්රියාත්මක වන බව ඔබට සහතික විය හැකිය.
C ++ 98 / C ++ 03 පිරිවිතරයේ වියුක්ත යන්ත්රය මූලික වශයෙන් තනි නූල් වලින් යුක්ත වේ. එබැවින් පිරිවිතරයට සාපේක්ෂව “සම්පුර්ණයෙන්ම අතේ ගෙන යා හැකි” බහු-නූල් සී ++ කේතය ලිවිය නොහැක. ඒ අයියා ගැන කිසිම දෙයක් පවා කියන්නේ නැහැ atomicity මතක මාර්ගන ගබඩා හෝ නියෝගයක් මාර්ගන ගබඩා mutexes වැනි දේවල් කමක්, කවදාවත් සිදු විය හැකි වන.
ඇත්ත වශයෙන්ම, විශේෂිත කොන්ක්රීට් පද්ධති සඳහා ඔබට ප්රායෝගිකව බහු-නූල් කේත ලිවිය හැකිය - pthreads හෝ Windows වැනි. නමුත් C ++ 98 / C ++ 03 සඳහා බහු-නූල් කේත ලිවීමට සම්මත ක්රමයක් නොමැත .
සී ++ 11 හි වියුක්ත යන්ත්රය මෝස්තරයෙන් බහු-නූල් කර ඇත. එය මනාව නිර්වචනය කළ මතක ආකෘතියක් ද ඇත ; එනම්, මතකයට ප්රවේශවීමේදී සම්පාදකයා කළ හැකි හා නොකළ හැකි දේ එයින් කියැවේ.
ගෝලීය විචල්යයන් යුගලයක් නූල් දෙකකින් සමගාමීව ප්රවේශ වන පහත උදාහරණය සලකා බලන්න:
Global
int x, y;
Thread 1 Thread 2
x = 17; cout << y << " ";
y = 37; cout << x << endl;
Thread 2 ප්රතිදානය කුමක් විය හැකිද?
C ++ 98 / C ++ 03 යටතේ මෙය නිර්වචනය නොකළ හැසිරීමක් නොවේ; ප්රමිතිය “නූල්” යනුවෙන් කිසිවක් ගැන නොසිතන හෙයින් ප්රශ්නයම අර්ථ විරහිත ය .
C ++ 11 යටතේ, ප්රති result ලය නිර්වචනය නොකළ හැසිරීමකි, මන්ද පැටවුම් සහ ගබඩා සාමාන්යයෙන් පරමාණුක නොවිය යුතුය. එය වැඩි දියුණුවක් ලෙස නොපෙනේ ... එසේම එය එසේ නොවේ.
නමුත් C ++ 11 සමඟ ඔබට මෙය ලිවිය හැකිය:
Global
atomic<int> x, y;
Thread 1 Thread 2
x.store(17); cout << y.load() << " ";
y.store(37); cout << x.load() << endl;
දැන් දේවල් වඩාත් රසවත් වේ. පළමුවෙන්ම, මෙහි හැසිරීම අර්ථ දක්වා ඇත. Thread 2 දැන් මුද්රණය කළ හැකිය 0 0
(එය Thread 1 ට පෙර ධාවනය වන්නේ නම්), 37 17
(එය Thread 1 ට පසුව ධාවනය වන්නේ නම්), හෝ 0 17
(Thread 1 x ට පැවරීමෙන් පසුව එය ක්රියාත්මක වන්නේ නම් එය y ට පැවරීමට පෙර).
එය මුද්රණය කළ නොහැකි දෙය නම් 37 0
, C ++ 11 හි පරමාණුක පැටවුම් / ගබඩා සඳහා පෙරනිමි ප්රකාරය අනුක්රමික අනුකූලතාව බලාත්මක කිරීමයි. මෙයින් අදහස් කරන්නේ සියලුම පැටවුම් සහ වෙළඳසැල් ඔබ ඒවා එක් එක් නූල් තුළ ලියා ඇති අනුපිළිවෙලට “සිදු වූවාක් මෙන්” විය යුතු අතර, නූල් අතර මෙහෙයුම් පද්ධතියට කැමති ආකාරයට අන්තර් සම්බන්ධ කළ හැකි බවයි. ඒ නිසා atomics පෙරනිමි හැසිරීම යන දෙකම සපයයි atomicity සහ ඇනවුම් කිරීම මාර්ගන ගබඩා සඳහා.
දැන්, නවීන CPU එකක, අනුක්රමික අනුකූලතාව සහතික කිරීම මිල අධික විය හැකිය. විශේෂයෙන්, සම්පාදකයා මෙහි ඇති සෑම ප්රවේශයක් අතරම පූර්ණ මතක බාධක විමෝචනය කරයි. නමුත් ඔබේ ඇල්ගොරිතමයට අක්රීය බර සහ ගබඩා ඉවසා සිටිය හැකි නම්; එනම්, එයට පරමාණුකතාව අවශ්ය නමුත් ඇණවුම් නොකරන්නේ නම්; එනම්, 37 0
මෙම වැඩසටහනේ ප්රතිදානය ලෙස එය ඉවසිය හැකි නම් , ඔබට මෙය ලිවිය හැකිය:
Global
atomic<int> x, y;
Thread 1 Thread 2
x.store(17,memory_order_relaxed); cout << y.load(memory_order_relaxed) << " ";
y.store(37,memory_order_relaxed); cout << x.load(memory_order_relaxed) << endl;
CPU වඩා නවීන, මෙය පෙර උදාහරණයට වඩා වේගවත් වීමට ඉඩ ඇත.
අවසාන වශයෙන්, ඔබට විශේෂිත බර සහ වෙළඳසැල් පිළිවෙලට තබා ගැනීමට අවශ්ය නම්, ඔබට ලිවිය හැකිය:
Global
atomic<int> x, y;
Thread 1 Thread 2
x.store(17,memory_order_release); cout << y.load(memory_order_acquire) << " ";
y.store(37,memory_order_release); cout << x.load(memory_order_acquire) << endl;
මෙය අපව නැවත ඇණවුම් කළ පැටවුම් සහ වෙළඳසැල් වෙත ගෙන යයි - එබැවින් 37 0
එය තවදුරටත් කළ හැකි නිමැවුමක් නොවේ - නමුත් එය අවම පොදු කාර්යයකින් සිදු කරයි. (මෙම සුළු උදාහරණයේ දී, ප්රති result ලය පූර්ණ අනුක්රමික අනුකූලතාවයට සමාන ය; විශාල වැඩසටහනක දී එය එසේ නොවේ.)
ඇත්ත වශයෙන්ම, ඔබට දැකීමට අවශ්ය එකම ප්රතිදානයන් නම් 0 0
හෝ 37 17
, ඔබට මුල් කේතය වටා මුටෙක්ස් ඔතා ගත හැකිය. නමුත් ඔබ මෙය බොහෝ දුරට කියවා ඇත්නම්, එය ක්රියාත්මක වන ආකාරය ඔබ දැනටමත් දන්නා බව මම විශ්වාස කරමි, මෙම පිළිතුර මා සිතුවාට වඩා දිගු වේ :-).
ඉතින්, පහළම තලය. Mutexes විශිෂ්ටයි, C ++ 11 ඒවා ප්රමිතිකරණය කරයි. නමුත් සමහර විට කාර්ය සාධන හේතූන් මත ඔබට පහළ මට්ටමේ ප්රාථමිකයන් අවශ්ය වේ (උදා: සම්භාව්ය දෙවරක් පරීක්ෂා කළ අගුලු දැමීමේ රටාව ). නව ප්රමිතිය මගින් මුටෙක්ස් සහ තත්ව විචල්යයන් වැනි ඉහළ මට්ටමේ ගැජට් සපයන අතර පරමාණුක වර්ග වැනි පහත් මට්ටමේ ගැජට් සහ මතක බාධකයේ විවිධ රසයන් ද සපයයි. එබැවින් දැන් ඔබට සම්පුර්ණයෙන්ම ප්රමිතියෙන් නිශ්චිතව දක්වා ඇති භාෂාව තුළ නවීන, ඉහළ කාර්යසාධනයක් සහිත සමගාමී චර්යාවන් ලිවිය හැකි අතර, ඔබේ කේතය සම්පාදනය කර අද දින පද්ධති දෙකෙහිම නොවෙනස්ව ක්රියාත්මක වන බවට ඔබට සහතික විය හැකිය.
අවංකව පැවසුවද, ඔබ විශේෂ expert යෙකු හා බැරෑරුම් පහත් මට්ටමේ කේතයක් මත වැඩ කරන්නේ නම් මිස, ඔබ බොහෝ විට මූටෙක්ස් සහ තත්ව විචල්යයන්ට ඇලී සිටිය යුතුය. ඒක තමයි මම කරන්න අදහස් කරන්නේ.
මෙම දේවල් පිළිබඳ වැඩි විස්තර සඳහා, මෙම බ්ලොග් සටහන බලන්න .