HARMONYOS سیستم متغیر بعدی: از تنوع تا مدل حافظه

در توسعه زبان Cangjie در Harmonyos بعدی ، سیستم متغیر پایه و اساس برنامه های ساختمانی است. تنوع ، انواع ارزش و انواع مرجع آن و همچنین استراتژی های مربوط به کامپایلر ، عمیقاً بر منطق در حال اجرا و عملکرد برنامه تأثیر می گذارد. به عنوان یک تکنسین که تجربه عملی غنی را در این زمینه جمع کرده است ، من این نکات کلیدی را بر اساس موارد واقعی تجزیه و تحلیل می کنم.
1. مقایسه/var مقایسه
(i) مزایای متغیرهای تغییر ناپذیر در برنامه نویسی همزمان
به زبان Cangjie ، let
برای تعریف متغیرهای تغییر ناپذیر استفاده می شود و var
برای تعریف متغیرهای قابل تغییر استفاده می شود. این دو متغیر در سناریوهای برنامه نویسی همزمان تفاوت معنی داری دارند و متغیرهای تغییر ناپذیر مزایای منحصر به فردی را در برنامه نویسی همزمان نشان می دهند.
در یک محیط همزمان ، چندین موضوع ممکن است به طور همزمان به داده های مشترک دسترسی پیدا کرده و اصلاح کنند ، که به راحتی می تواند باعث رقابت داده ها و ناسازگاری شود. به عنوان مثال ، هنگامی که عملیات چند رشته ای روی پیشخوان های مشترک:
// Assume this is in a concurrent environment
var counter = 0
// Thread 1 execution
counter++
// Thread 2 execution
counter++
از آنجا که موضوع 1 و موضوع 2 ممکن است مقدار آن را بخوانند و اصلاح کنند counter
در عین حال ، ارزش نهایی counter
ممکن است مورد انتظار 2 نباشد ، اما 1 (با فرض اینکه موضوع 1 و موضوع 2 مقدار را بخوانید counter
0 است ، سپس 1 را اضافه کنید و دوباره آن را بنویسید ، که اتفاق می افتد).
با استفاده از متغیر تغییر ناپذیر let
می تواند به طور موثری از این نوع مشکل جلوگیری کند. از آنجا که یک متغیر تغییر ناپذیر آغاز می شود ، ارزش آن را نمی توان اصلاح کرد ، که خطر رقابت داده ها را از بین می برد. برنامه نویسی همزمان ، ما می توانیم داده های مشترک را به عنوان متغیرهای تغییر ناپذیر تعریف کنیم و سپس با استفاده از برنامه نویسی عملکردی پردازش می کنیم. برای مثال ، هنگام محاسبه نتایج عملیات داده های جدید ، هر یک از داده ها را می توان به عنوان Dataination Dataination در نظر گرفت. Data.in به این روش ، هر موضوع یک کپی داده مستقل را اجرا می کند و با یکدیگر تداخل نخواهد کرد ، بنابراین از سازگاری داده ها و ثبات برنامه اطمینان می دهد.
2. تجزیه و تحلیل عمیق از نوع ارزش/مرجع
(i) تفاوت در رفتار کپی بین ساختار و کلاس (نمودار تخصیص حافظه)
به زبان Cangjie ، struct
متعلق به نوع ارزش و class
متعلق به نوع مرجع است. تفاوتهای آشکاری در رفتار کپی آنها وجود دارد ، که از نزدیک با روش تخصیص حافظه ارتباط دارد.
برای نوع ارزش struct
، یک نسخه جدید هنگام انجام تکالیف ایجاد می شود. برای مثال:
struct Point {
var x: Int
var y: Int
}
main() {
let p1 = Point(x: 1, y: 2)
var p2 = p1
p2.x = 3
println("p1.x: \(p1.x), p2.x: \(p2.x)")
}
در کد فوق ، چه زمانی p2 = p1
با p2
یک نسخه از p1
، اصلاح p2.x
تأثیر نخواهد گذاشت p1.x
، و نتیجه خروجی “p1.x: 1 ، p2.x: 3” است. از دیدگاه تخصیص حافظه ، p1
وت p2
فضای حافظه مستقل خود را در پشته قرار دهید و همان مقدار داده را ذخیره کنید ، همانطور که در زیر آمده است:
graph TD;
A[stack memory] --> B[p1(x:1,y:2)];
A --> C[p2(x:1,y:2)];
برای نوع مرجع class
، عملیات واگذاری فقط یک رابطه مرجع ایجاد می کند. برای مثال:
class Point {
var x: Int
var y: Int
init(x: Int, y: Int) {
this.x = x
this.y = y
}
}
main() {
let p1 = Point(x: 1, y: 2)
let p2 = p1
p2.x = 3
println("p1.x: \(p1.x), p2.x: \(p2.x)")
}
اینجا ، بعد از p2 = p1
با p1
وت p2
در حافظه پشته به همان شیء اشاره کنید. اصلاح کننده p2.x
تأثیر خواهد گذاشت p1.x
، و نتیجه خروجی “p1.x: 3 ، p2.x: 3” است. وضعیت تخصیص حافظه به شرح زیر است:
graph TD;
A[stack memory] --> B[p1 (points to objects in heap memory)];
A --> C[p2 (points to the same object in heap memory)];
D[heap memory] --> E[object(x:1,y:2, then becomes x:3,y:2)];
درک این تفاوت در رفتار کپی برای نوشتن کد مناسب ضروری است. در توسعه واقعی ، در صورت نیاز به یک کپی داده مستقل ، نوع ارزش باید انتخاب شود. اگر می خواهید داده ها را به اشتراک بگذارید و استفاده از حافظه را بهبود بخشید ، باید نوع مرجع انتخاب شود.
3. استراتژی محافظه کارانه کامپایلر
(i) اصل گزارش خطای اولیه سازی متغیر در بلوک آزمایشی
به زبان Cangjie ، کامپایلر یک استراتژی محافظه کارانه را برای اداره اولیه سازی متغیر اتخاذ می کند ، که به ویژه در آن آشکار است try-catch
block. برای مثال:
main() {
let a: String
try {
a = "1"
} catch (_) {
a = "2" // Error, cannot assign to immutable value
}
}
کد فوق خطایی را گزارش می کند زیرا کامپایلر فرض می کند که همه try
بلوک ها همیشه اجرا می شوند و استثنائات همیشه پرتاب می شوند. a
ممکن است وارد شود catch
بلوک بدون ابتدای کار در try
بلوک ، و متغیر تغییر ناپذیر a
نمی توان چندین بار اختصاص یافت ، بنابراین کامپایلر خطایی را گزارش می کند.
از دیدگاه کامپایلر ، این استراتژی محافظه کارانه اطمینان از امنیت و ثبات Code.in منطق برنامه پیچیده ، کد در try
بلوک ممکن است شامل عملیات مختلفی باشد که ممکن است استثنائات را به وجود آورد ، و کامپایلر نمی تواند تعیین کند که آیا متغیرهای موجود در آن try
بلوک آغاز می شود. بنابراین ، برای جلوگیری از خطاهای احتمالی زمان اجرا ، کامپایلر یک استراتژی محافظه کارانه را برای گزارش یک پیام خطا به این وضعیت اتخاذ می کند. در توسعه واقعی ، ما باید به رفتار کامپایلر توجه کنیم و به طور منطقی به طور منطقی رفتار کنیم ، مانند اولیه سازی متغیرهای خارج از متغیرهای خارج از try-catch
بلوک ، یا تنظیم ساختار کد را با توجه به منطق خاص برای برآورده کردن نیازهای کامپایلر و اطمینان از اینکه برنامه می تواند به درستی تهیه و اجرا شود.