<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Farchid</title>
        <link>https://virgool.io/feed/@farshidboroomand</link>
        <description>un homme normal :)</description>
        <language>fa</language>
        <pubDate>2026-06-16 15:57:15</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/138115/avatar/whoo1r.jpg?height=120&amp;width=120</url>
            <title>Farchid</title>
            <link>https://virgool.io/@farshidboroomand</link>
        </image>

                    <item>
                <title>یه Hello world با استفاده از RabbitMQ و گولنگ</title>
                <link>https://virgool.io/@farshidboroomand/%DB%8C%D9%87-hello-world-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-rabbitmq-%D9%88-%DA%AF%D9%88%D9%84%D9%86%DA%AF-g5f0rnhj50iq</link>
                <description>سورس اصلی مقاله :)ربیت ام کیو یک Message Broker یا به عبارتی یک رابط هستش برای پیام ها هستش، پیام هارو دریافت و ارسال میکنه، دقیقا میتونین مثل یک اداره پست بهش نگاه کنین، وقتی قصد اینو دارین که یک بسته یا نامه ارسال کنین، خیالتون راحته که بعد از یک زمانی بسته شما به نوبت ارسال خواهد شد حالا این آقای ربیت ام کیو دقیقا شده همین اداره پست یا باکس پستی و نامه ارسالی شما.تفاوت بین این ابزار با اداره پست اینه که بجای کاغذ داره دیتای باینری این وسط جابجا میکنه !حالا یه سری اصطلاحات هستش که این دوستمون داره ازش استفاده میکنه که قطعا شما هم میدونینProducerProducing means nothing more than sending. A program that sends messages is a producerQueueA queue is the name for a post box which lives inside RabbitMQ. Although messages flow through RabbitMQ and your applications, they can only be stored inside a queue. Many producers can send messages that go to one queue, and many consumers can try to receive data from one queue. This is how we represent a queue:صف یا کیو دقیقا همون باکس پستی هستش که برای این ابزار درنظر گرفته شده، اگرچه مسیج ها میتونن در ربی ام کیو در جریان باشن، اونا فقط میتونن توی یک صف قرار بگیرن.ایجاد کننده های مسیج ها یا همون producers میتونن به یک صف مسیج هاشونو ارسال کنن و مصرف کننده ها یا دریافت کننده ها (consumers) هم میتونن تلاش کنن برای دریافت دیتا از یک صفConsumerConsuming has a similar meaning to receiving. A consumer is a program that mostly waits to receive messages:مصرف کننده یا دریافت کننده هم برنامه ای هستش که برای دریافت پیام ها داره صبر میکنه که دریافتشون کنهخوب حالا ما با استفاده از کلاینت گولنگ برای این ابزار یه برنامه خیلی خیلی خیلی احمقانه و ساده مینویسیم ببینیم چطوری این دوستمون کار میکنه :)دو بخش خواهیم داشت۱- بخشی که نقش ارسال کننده پیام داره یعنی همون آقای producer۲ بخشی که نقش دریافت کننده پیام داره یعنی همون خانم consumerخوب همونطوری که توی دیاگرام مشخصه p همون producer هستش و c هم همون consumer و باکس وسطی هم که صف یا همون Queue هستشربیت ام کیو با پروتکل های مختلفی میتونه ارتباط برقرار کنه، همونطوری که توی مقاله اومده ما از AMQP 0-9-1 قراره استفاده کنیمما از این کلاینت داریم استفاده میکنیمgo get github.com/rabbitmq/amqp091-goخوب حالا این کلاینت داریم و بریم بنویسیم ببینیم چی میشهپروسه ارسال پیامما یک فایل send.go خواهیم داشت و یک فایل دریافت مسیج به اسم receive.goپابلیشر یا ارسال کننده به ربیت ام کیو وصل خواهد شد و یک پیام ارسال میکنم و تموم میشه کارش https://gist.github.com/farshidboroomand/e691314b6e0068072bb45fc4ce28ebd5 پروسه دریافت پیامخوب این خانم دریافت کننده مسیج کارش اینه که listen میکنه برای مسیج های دریافتی و اونو پرینت میکنهما یه فایل receive.go هم خواهیم داشت https://gist.github.com/farshidboroomand/73be44807a9e973b98b7a786c95ee95b خوب حالا توی دو ترمینال جداگانه اول فایل receive.go اجرا کنین و بعدش توی اون یکی فایل send.go و میبینین که داره ارتباط برقرار میشهدر ضمن اینم کامپوز فایلش شاید به کارتون اومد :) https://gist.github.com/farshidboroomand/6dc1b19107d0d8bbafbc8eb040dc42e3 </description>
                <category>Farchid</category>
                <author>Farchid</author>
                <pubDate>Wed, 06 Jul 2022 11:38:15 +0430</pubDate>
            </item>
                    <item>
                <title>پوینترها در زبان گو</title>
                <link>https://virgool.io/golangpub/%D9%BE%D9%88%DB%8C%D9%86%D8%AA%D8%B1%D9%87%D8%A7-%D8%AF%D8%B1-%D8%B2%D8%A8%D8%A7%D9%86-%DA%AF%D9%88-zefhs3sbze0a</link>
                <description>منبع :)پوینترها یک ابزار اولیه اما خیلی قدرتمند هستند که معمولا به عنوان یک چیز سخت و مزخرف ازش یاد میشه موقع برنامه نویسی !پوینترها ساخته شدند برای تسریع و کمک به جهت جابجایی دیتا در کدها بدون اینکه نیاز باشه از یک متغیر کپی گرفته یا ساخته بشه، خوب که چی بشه دوست من !؟ جوابش سادست =&gt; مصرف کمتر مموری :)در برخی زبان ها این concept کلا دوری شده ازش، بعضی ها هم تقریبی سعی کردن مدیریتش کنند اما در زبان گو پوینترها به معنای واقعی یک ابزار خوب برای بهبود performance ازش استفاده میشه.خوب بریم سراغ این دوستمون پوینتر یک پوینتر متغیری هستش که اشاره میکنه به محل خاصی از مموری که مقداری در اونجا ذخیره شده، بنابراین شما یک متغیری را ایجاد کرده و مقداری در این قرار میدهید و خیلی ساده به جای اینکه مقدار واقعی اونو بخواین بخونین از آدرسش می تونین استفاده کنین.به کد زیر توجه کنیدpackage main

import (
   &amp;quotfmt&amp;quot
)

func main ( ) {
   myString := &amp;quota string value&amp;quot
   fmt.Println(myString)

   myInteger := 1
   fmt.Println(myInteger)
}ما دوتا متغیر ساختیم و پرینتش کردین ! هیچ کار خاصی و عجیبی هم انجام ندادیم هنوزاگر ما یک متغیری را به یک تابعی پاس بدیم، زبان میاد یک کپی از اونا میگیره و در داخل تایع ازش استفاده میکنه مثل این:func myFunction(s string){
   fmt.Println(s)
}func main() {
   myOtherString := &amp;quotanother message here&amp;quot
   myFunction(myOtherString)
}وقتیکه تابع myFunction  مقدار رشته ای s دریافت میکنه و پرینتش میکنه روی کنسول گولنک (و اکثر زبان ها) یک کپی از مقداری که ارسال شده درست میکنه در داخل تابع، وقتیکه تابع کارش به آخر میرسه اینجاست که Garbage collector میاد به سراغ این متغیر ها.خوب حالا همون کارو با پوینتر انجامش میدیمfunc myFunctionWithPointers(s *string){
   fmt.Println(s, *s)
}func main() {
   myOtherString := &amp;quotanother message here&amp;quot
   myFunctionWithPointers(&amp;myOtherString)
}خوب ایندفعه ما یکسری کارکتر جدید و عجیب داریم که اضافه شدن مثل * و &amp;در داخل () main علامت &amp; داره به زبان گو اعلام میکنه که این یک آدرسی هستش از یک متغیر، حالا گولنگ میاد میره دیتا تایپ و جایی که این مقدار در مموری قرار گرفته پیدا میکنه و نهایتا آدرس ارسال میشه به فانکشندر تابع myFunctionWithPointers علامت ستاره (*) داره به گو میگه که من دارم یک آدرس دریافت میکنم با دیتا تایپ رشته یا string. چیزی که مهمه اینکه پوینترها به تایپ نیاز دارند، پوینتر به یک عدد، پوینتر به یک رشته و یا پوینتر به یک slice و و و بعد از اینکه دیتاتایپ مشخص شد، اون در بدنه تابع ما داریم به زبان گو میگیم که s یک پوینتر است و مقداری که در اون جا ذخیره شده برای ما برمیگردهخوب حالا بریم سراغ structure type myStructure struct {
   Name string
}

func main() {
   structure := myStructure{Name: &amp;quotMyName&amp;quot}
   structureFunction(&amp;structure)
}

func structureFunction(e *myStructure){
   fmt.Println(e, *e, e.Name, (e).Name)
}اولا ما مقدار استراکچر داریم پرینت میکنیم اما با مقدار &amp; میبینیم که نشون داده میشه خوب این یعنی اینکه، یک پوینتر است به استراکچر با آن محتواوقتی که ما از ستاره استفاده میکنیم،‌ما داریم میگیم که مقدارها گرفته بشن بنابراین {MyName} که یک استراکچر فرمت شده است را دریافت میکنیموقتیکه شما دسترسی پیدا میکنی به یک فیلد از پوینتر استارکچر، گو میاد دقیقا به شما مقدار برمیگردونه. مورد آخر هم دقیقا داره همون کار انجام میده که دیگه بهش نیازی نیست و همون روش قبل کفایت میکنهحالا فرض کنین ما میخوایم متغیر آپدیت کنیم داخل تابعfunc main() {
   sliceValues := []string{&amp;quota&amp;quot,&amp;quotb&amp;quot, &amp;quotc&amp;quot}
   appendToSlice(sliceValues)
   fmt.Println(sliceValues)
}

func appendToSlice(c []string){
   fmt.Println(c)
   c = append(c, &amp;quotd&amp;quot)
}چی شده !!؟عدم استفاده از این دوستمون پوینتر نتیجش شد اینکه آپدیتی شکل نگرفت چون خارج از تابع بوده!func main() {
   sliceValues := []string{&amp;quota&amp;quot,&amp;quotb&amp;quot, &amp;quotc&amp;quot}
   appendToSliceWithPointer(&amp;sliceValues)
   fmt.Println(sliceValues)
}

func appendToSliceWithPointer(c *[]string){
   fmt.Println(*c)
   *c = append(*c, &amp;quotd&amp;quot)
}خوب بنظر ساده میاد،‌حالا چه اتفاقی می افته اگر ما maps داشته باشیم !؟func main() {
   myMap := map[string]int{
      &amp;quota&amp;quot: 1,
      &amp;quotb&amp;quot: 2,
      &amp;quotc&amp;quot: 3,
   }
   maps(myMap)
   fmt.Println(myMap)
}

func maps(c map[string]int){
   c[&amp;quotd&amp;quot] = 4
   fmt.Println(c)
}توی این مثال، تغییر در map رفتارش متفاوت بود !آپدیت شدش ! داخل فانکشن به مقدار original map !‌ مگه داریم‌!؟چرا چون که خود maps در واقع پونتر هستند و در نتیجه ما نیازی نداریم کار خاصی با map ها بکنیمیه چیز کوچولو دیگه هم هست که باید بهش توجه کرد حدس بزنین ! تابع ها هم همچنین پوینتر هستند !func main() {
   f := &amp;myFunc
}
 
func myFunc(){
 
}خوب این کار نمیکنه از اونجایی که myFunc خودش پوینتر هستش !حالا از اونجایی که پوینتر عملا یک دیتاتایپ هستش، ورودی های تابع رفتار مشابهی دارندtype myStructure struct {
   Name string
}

func (ms myStructure) noPointer(){
   ms.Name = &amp;quotxxxx&amp;quot
   fmt.Println(ms.Name)
}

func (ms *myStructure) withPointer(){
   ms.Name = &amp;quotyyyy&amp;quot
   fmt.Println(ms.Name)
}

func main() {
   theStructure := myStructure{Name: &amp;quotMyName&amp;quot}
   theStructure.noPointer()
   fmt.Println(theStructure.Name)

   theStructure.withPointer()
   fmt.Println(theStructure.Name)
}وقتیکه ورودی به عنوان یک structure استفاده میشه، مقدار تاثیری روش گذاشته نمیشه خارج از اون تابعوقتیکه ورودی مدیریت میشه به عنوان یک پوینتر، مقدار رفتارش همونی میشه که ما انتظار داریم اما اگر شما بخواین متد مستقیما صدا بزنین:func (ms myStructure) noPointer(){
   fmt.Println(&amp;quotNot a pointer&amp;quot)
}

func (ms *myStructure) withPointer(){
   fmt.Println(&amp;quota pointer&amp;quot)
}

func main() {
   myStructure{}.noPointer()
   myStructure{}.withPointer()
}دومین تابع یعنی withPointer خیلی ساده اجرا نمیشه، withPointer یک ورودی لینک شده هستش به pointer to myStructure دیتا تایپ و {} myStructure یک instance از myStructure ما میتونیم درستش کنیم با instancing structure و بعدش اضافه کردن یک پوینتر به اونtype myStructure struct {
   Name string
}

func (ms myStructure) noPointer(){
   fmt.Println(&amp;quotNot a pointer&amp;quot)
}

func (ms *myStructure) withPointer(){
   fmt.Println(&amp;quota pointer&amp;quot)
}

func main() {
   myStructure{}.noPointer()
   ms := &amp;myStructure{}
   ms.withPointer()
}خوب این تمام چیزیه که شما نیاز دارین بهش برای شروع کار با پوینتر ها :)سعی میکنم یه مقاله دیگه پیدا کنم یکم مباحث advance تری بگه. حالا برای شروع همچین بد هم نیستش :)مرسی</description>
                <category>Farchid</category>
                <author>Farchid</author>
                <pubDate>Fri, 03 Sep 2021 23:25:15 +0430</pubDate>
            </item>
                    <item>
                <title>مفهوم Context در زبان Go</title>
                <link>https://virgool.io/golangpub/%D9%85%D9%81%D9%87%D9%88%D9%85-context-%D8%AF%D8%B1-%D8%B2%D8%A8%D8%A7%D9%86-go-jascblcr4oqq</link>
                <description>منبعدوستان من توی ترجمه Context واژی خوبی واقعا پیدا نکردم که بشه ازش استفاده کرد پس از خود همین واژه استفاده میکنم شما هم به بزرگی خودتون ببخشید :)از کانتکس ها در برنامه هایی که با گولنگ توسعه داده شده است برای مدیریت و کنترل هرچه بهتر مواردی همچون کنسل کردن، اشتراک گذاری دیتاها در برنامه نویسی اصطلاحا همروند به کار گرفته شده است.خوب این یه چیز بدیهی به نظر میرسه اما در حقیقت نه آن چنان ! یعنی چی !؟ نقطه ی شروع کانتکس ها پکیج کانتکس هستش که تقریبا خیلی پرکاربرد و میتونیم بگیم همه کاره هستش در این زبان. اگر شما هنوز با کانتکس ها سرو کله نزدید قطعا خیلی زود این اتفاق براتون می افته شایدم بهش برخوده باشین ولی توجه کافی نکرده باشید. در کل اکوسیستم زبان این پکیج یک کامپوننت کلیدی به حساب می آید بطوری که استفاده از اون خیلی گسترده هستش و پکیج های دیگه هم ازش بهره میبرند.داکیومنت این پکیج از اینجا قابل دسترس هستشContext With Valueیکی از بیشتری استفاده کانتکس ها برای Share Data هستش و یا Use Request Scoped Value. وقتیکه تعداد خیلی زیادی فانکشن دارین و میخواین دیتا بین اونها پخش یا توزیع کنید اینجا میتونید از کانتکس ها استفاده کنید. بهترین و ساده ترین روش استفاده از فانکشن context.WithValue هستش. این فانکشن یک کانتکس جدید بر اساس کانتکس والد می سازه و یک مقداری به کلید داده شده اختصاص میده.اگر بخواین بفهمین اون پشت چه خبره میشه گفت. از اونجایی که کانتکس شامل map در داخل خودش هست پس شما خیلی راحت میتونین بر اساس کلید مقدارهارو دریافت کنید.این خیلی قدرتمنده و دست شمارو باز میزاره چرا که بهتون اجازه میده که هر نوعی از دیتا داخل کانتکس ذخیره کنید. مثال ست کردن و دریافت کردن دیتا هم در زیر میتونین ملاحظه کنید.package main
import (
	&amp;quotcontext&amp;quot
	&amp;quotfmt&amp;quot
)
func main() {
	ctx := context.Background()
	ctx = addValue(ctx)
	readValue(ctx)
}
func addValue(ctx context.Context) context.Context {
	return context.WithValue(ctx, &amp;quotkey&amp;quot, &amp;quottest-value&amp;quot)
}
func readValue(ctx context.Context) {
	val := ctx.Value(&amp;quotkey&amp;quot)
	fmt.Println(val)
}چیز مهمی که پشت دیزاین این پکیج کانتکس وجود داره اینه که همه چیز یک context.Context جدید از نوع struct برمیگردونند.خوب این دیگه چیه ؟شما مجبور هستین که یادتون باشه با مقدار برگشتی باید یه کاری به هر حال انجام بدید و حتی کانتکس های قدیمی با جدیدها جایگزین کنید. این یک امر مهم در دیزاین با ثبات هستش.استفاده از این تکنیک که شما میاین با استفاده از context.Context مقداری ارسال میکنین به فانکشن های همروند. تا وقیکه مدیریت خوبی روی کانتکس ارسالی دارین خیلی روش خوبیه که scoped value ها را بین فانکشن های همروند تقسیم کنید.چی شد !؟یعنی هر کانتکس، مقدار خودش داخل اسکوپ خودش نگهداری میکنه. دقیقا کاری که پکیج net/http داره انجام میده برای هندل کردن HTTP Requests. باید مثال بزنیم تا روشن بشه چون همچنان گنگ هستش.میدلورهابهترین مثالی که میشه اینجا آورد برای این کیس میدلورهایی هستند که درخواست های ورودی هندل میکنند.تایپ http.Request شامل کانتکس هم هستش که میتونه با خودش scoped values داخل پایپلاین HTTP بیاره.این کار خیلی مرسوم هستش که یک درخواستی که بالاتر بهش گفتیم پایپلاین،‌میدلورها میان یکسری تغییرات در کد اعمال میکنند یا به عبارتی به context. و این تکنیک خیلی خوبیهpackage main
import (
	&amp;quotcontext&amp;quot
	&amp;quotlog&amp;quot
	&amp;quotnet/http&amp;quot
	&amp;quotgithub.com/google/uuid&amp;quot
	&amp;quotgithub.com/gorilla/mux&amp;quot
)
func main() {
	router := mux.NewRouter()
	router.Use(guidMiddleware)
	router.HandleFunc(&amp;quot/ishealthy&amp;quot, handleIsHealthy).Methods(http.MethodGet)
	http.ListenAndServe(&amp;quot:8080&amp;quot, router)
}
func handleIsHealthy(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	uuid := r.Context().Value(&amp;quotuuid&amp;quot)
	log.Printf(&amp;quot[%v] Returning 200 - Healthy&amp;quot, uuid)
	w.Write([]byte(&amp;quotHealthy&amp;quot))
}
func guidMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		uuid := uuid.New()
		r = r.WithContext(context.WithValue(r.Context(), &amp;quotuuid&amp;quot, uuid))
		next.ServeHTTP(w, r)
	})
}همانطور که ملاحظه میکنین میبینین که فانکشن guidMiddleware به درخواست attach شده و هر چیزی که ارسال بشه این کد بهش اعمال یا اضافه میشه.Context Cancellationفیچر خیلی خوبی که گولنگ در اختیار ما قرار ماده همین Context Cancellation هستش، خوب این دوستمون چی هست و چی کار میکنه برامون ؟دقیقا برای موقعی خوبه که شما میخواین تعداد خیلی زیادی از گوروتین هارو بهشون بگین کنسل بشن. برای مثال فرض کنین یک فانکشن دارین که ده ها گوروتین استارت میکنه. اون فانکشن اصلی صبر میکنه تا تمام گوروتین ها کارشون تموم بشه و یا یک سیگنال کنسل ایجاد بشه قبل از اینکه بقیه پروسه ادامه پیدا کنه.اگر سیگنا کنسل دریافت بشه ما میخوایم اینو پخشش کنیم به همه ی گوروتین هاخوب که چی بشه !؟شما دیگه منابع کامپیوتر هدر ندادین اگر یک کانتکس مشترک بین همه گوروتین های خودتون تقسیم کرده باشین.خیلی ساده برای ایجاد یک کانتکس با ویژگی کنسل شدن فقط کافیه (ctx)context.WithCancel صدا زده بشه و کانتکس به عنوان ورودی پاس داده بشه.مثال عملیش میشه اینکه مثلا ما داریم یه درخواستی به یک وب سرویسی می زنیم و اگر جوابی برای ما برنگرده در طی اون زمانی که مشخص کردیم وقتی که response برمیگرده تمام درخواست ها را کنسل میکنیم.package main
import (
	&amp;quotcontext&amp;quot
	&amp;quotfmt&amp;quot
	&amp;quotio/ioutil&amp;quot
	&amp;quotnet/http&amp;quot
	neturl &amp;quotnet/url&amp;quot
	&amp;quottime&amp;quot
)

func queryWithHedgedRequestsWithContext(urls []string) string {
	ch := make(chan string, len(urls))
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	for _, url := range urls {
		go func(u string, c chan string) {
			c &lt;- executeQueryWithContext(u, ctx)
		}(url, ch)

		select {
		case r := &lt;-ch:
			cancel()
			return r
		case &lt;-time.After(21 * time.Millisecond):
		}
	}
	return &lt;-ch
}

func executeQueryWithContext(url string, ctx context.Context) string {
	start := time.Now()
	parsedURL, _ := neturl.Parse(url)
	req := &amp;http.Request{URL: parsedURL}
	req = req.WithContext(ctx)

	response, err := http.DefaultClient.Do(req)

	if err != nil {
		fmt.Println(err.Error())
		return err.Error()
	}

	defer response.Body.Close()
	body, _ := ioutil.ReadAll(response.Body)
	fmt.Printf(&amp;quotRequest time: %d ms from url%s\n&amp;quot, 
        time.Since(start).Nanoseconds()/time.Millisecond.Nanoseconds(), url)
	return fmt.Sprintf(&amp;quot%s from %s&amp;quot, body, url)
}هر درخواست در یک گوروتین جداگانه اجرا میشود، کانتکس به تمامی درخواست هایی که زده شده اند فرستاده میشود. تنها چیزی که با کانتکس انجام شده اینه که اون ارسال شده به HTTP client. این اجازه میده تا پروسه کنسل شدن خیلی راحت صدا زده بشه و کانکشن برقرار باشه.Context Timeoutاین پترن خیلی مرسوم هستش برای ارسال درخواست خای خارجی مثل کوعری های دیتابیس یا گرفتن دیتا از یک سرویس دیگر چه از طریق HTTP و یا gRPC. مدیریت این سناریوها با استفاده از این پکیج خیلی راحت انجام میشه. تنها کاری که لازم دارین انجان بدین صدا زدن فانکشن context.WithTimeout(ctx, time) در واقع کانتکس و زمان باید پاس داده بشه.ctx, cancel := context.WithTimeout(context.Background(), 100 * time.Millisecond)با این کار شما فانکشن کنسل دریافت میکنید برای موقعی که بخواین صداش کنین. دقیقا مثل Context Cancellation قبلی کار میکنه</description>
                <category>Farchid</category>
                <author>Farchid</author>
                <pubDate>Sun, 15 Aug 2021 20:46:31 +0430</pubDate>
            </item>
                    <item>
                <title>تفاوت بین Stack و ‌Heap</title>
                <link>https://virgool.io/@farshidboroomand/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-%D8%A8%DB%8C%D9%86-stack-%D9%88-heap-zmtewpvjtwry</link>
                <description>از استک برای اختصاص دادن به استاتیک مموری و از هیپ برای اختصاص دادن به داینامیک مموری استفاده میشه، به هر حال هر دو در Ram ذخیره میشن.متغیرهای اختصاص داده شده در استک مستقیم در مموری ذخیره و دسترسی به این مموری بسیاری سریع است. پروسه اختصاص یافتن زمانی اتفاق میفته که برنامه اصطلاحا کامپایل شده باشه.وقتیکه یک فانکشن یا یک متد به عبارتی فانکشن های دیگه ای صدا میزنند که ممکنه فانکشن های دیگه ای هم صدا زنده بشه و و و. اجرای همه ی این فانکشن ها متوقف میشه تا وقیکه دقیقا آخرین فانکشن مقدارش برگرده.استک همیشه روشش LIFO هستش یعنی چی، خیلی ساده هر چی آخر میاد اول هم میره بیرون.(آخرین بلاکی که رزرو شده دقیقا بلاک بعدی هستش که آزاد خواهد شد). اینطوری خیلی راحت میشه استک دنبالش کرد و فهمیدش. آزادسازی یک بلاک از استک چیزی نیست جز تنظیم کردن یک Pointerمتغیرهای اختصاص داده شده در هیپ مموری اختصاصی خودشون دارند در زمان اجرا و دسترسی به این مموری مقداری کند تر است. اما سایز هیپ فقط محدود به سایز Virtual Memory هستش.المان هیپ هیچ وابستگی به یکدیگر ندارند و بصورت رندوم قابل دسترس هستند. یک بلاک میتواند در هر زمانی بهش اختصاص داده بشه و در هرزمانی هم آزاد بشه. همین باعث میشه دنبال کردن اینکه کدوم بخش از هیپ اختصاص داده شده یا آزاد هستش سخت بشه.استک زمانی بهتره استفاده که شما دقیقا میدونید چه مقدار دیتا نیازدارید قبل از کامپایل و در واقع خیلی هم زیاد نیست. از اون طرف اگر نمیدونید چقدر دیتا نیاز هستش در زمان اجرا و مقدار دیتا زیاد هستش بهتره از هیپ استفاده بشه.در یک موقعیت Multi thread هر یک از ترد ها استک خودشون دارند اما اونا هیپ share میکنند.منبع</description>
                <category>Farchid</category>
                <author>Farchid</author>
                <pubDate>Fri, 13 Aug 2021 22:11:23 +0430</pubDate>
            </item>
                    <item>
                <title>تفاوت بین پروسه و ترد در چیست ؟!</title>
                <link>https://virgool.io/@farshidboroomand/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-%D8%A8%DB%8C%D9%86-%D9%BE%D8%B1%D9%88%D8%B3%D9%87-%D9%88-%D8%AA%D8%B1%D8%AF-%D8%AF%D8%B1-%DA%86%DB%8C%D8%B3%D8%AA-xxnr6j9yxx6v</link>
                <description>منبعموقع خوندن این مقاله شاید شما دارین موزیک گوش میکنین یا مشغول کار دیگه ای هستین. به عبارتی،‌ شما ممکنه در لحظه چندین کار بصورت پارالل دارین انجام میدین. دقیقا همین کیس توی کامپیوتر هم هست، برای پروسه هایی که بصورت پارالل دارن اجرا میشن ترد ها مورد استفاده قرار میگیرند.در بازی های موبایل یا PC اجسامی مثل ماشن،‌کامیون و چیزهای دیگه اینها همگی تردهایی هستند که دارن توی این اپلیکیشن بازی اجرا میشن. یا یه مثال دیگه،‌ مرورگر وب شما یک ترد داره عکس یا ویدیو لود میکنه از اون طرف ترد های دیگه دارن دیتارو میگیرن. بنابراین یک اپلیکیشن ممکنه نیازمند اجرای جندین تسک بصورت پارالل باشه. ترها هم برای همین منظور به کار گرفته میشن برای کارهای موازی.تردیک ترد مجموعه ای از stack, program counter هستش که داخل یک پروسه وجود داره. به عبارتی در پروسه ساکن است.بنابراین تردها نمیتونند خارج از پروسه ها وجود داشته باشند. همچنین هر ترد مختص دقیقا یک پروسه است.اطلاعاتی مثل code segment, files, data segment میتونه بین تردهای مختلف share بشه.تردها برایبهبود بخشیدن به اپلیکیشن ها استفاده میشدن بصورت موازی. در واقع فقط یک ترد در آن واحد اجرا میشه اونم توسط ‌CPU. جالب اینجاست که CPU خیلی سریع سوییچ بین ترد ها و این خطا بوجود بیاد که فرض بشه که تردها بصورت پارالل دارن اجرا میشن.تردها همچنین به light-weight processes یا پروسه های سبک هم شناخته میشنشکل بالا بیانگر پروسه سینگل ترد و پروسه مالتی ترد هستش. و همانطوری که ملاحظه میکنین هر ترد registers, stack, counter خودشو داره فقط code, data ,files بصورت مشترک هستش.انواع تردهاUser-Level Threadاین نوع ترد توسط کاربران مدیریت میشه و کرنل هیچ خبری ازش ندارهاین تردها سریع ساخته شده و راحت میدیرت میشنکرنل مدیریتشون میکنه به شرط اینکه پروسه سینگل ترد باشهپیاده سازی که شده با استفاده از user-level libraries بوده و نه با صدا زدن سیستم. هیچ اتفاقی توی سیستم عامل نمی افته وقتیکه کانتکس ترد سوییچ میشه.هر پروسه جدول اختصاصی ترد خودشو داره برای track کردن ترد هاKernel-Level Threadکرنل درمورد ترد اطلاع داره و توسط OS هم ساپورت  میشهتردها با صدا زدن سیستم ساخته و مورد استفاهده قرار میگیرند.جدول ترد برای هر پروسه دیگه اینجا مطرح نیست و کرنل هستش که این جدول نگهداری میکنه برای Track کردن ترد های موجود در سیستمدر مقایسه با نوه user-level thread این نوع کند تر ساخته و مدیریت میشود.مزیت تردها۱− عملکرد: ترد ها در کل عملکرد یک برنامه بهبود می بخشه۲− توزیع منابع: از اونجایی که یک ترد میتونه خیلی راحت مموری و منابع هر پروسه به اشتراک بزاره. برنامه های دیگه که میخوان کارهای مختلفی انجام بدن بهشون اجازه این کارو میده اما فقط در یک محیط مشخص۳− معماری مصرف چندین پردازشگر (Utilization of Multiple Processor Architecture)تردهای گوناگون میتونن بر روی چندین پردازشگر اجرا بشن. بنابراین، کارایی پردازشگر بهتر خواهد شد۴− کاهش زمان Context Switching تردها زمان کانتکس سوییچینگ کم میکنن و فضای حافظه مجازی همان مقدار باقی میمونه۵− همروندی: تردها همروندی در یک پروسه آسان کرده اند۶− برنامه نویسی با تکنیک های پارالل خیلی آسان تر پیاده سازی میشنفرق بین پروسه و ترد۱− پروسه یعنی برنامه ای که در حال حاضر دارد اجرا میشود، ولی ترد یک موجودیتی است داخل پروسه که میتواند برنامه ریزی شود برای اجرا۲− پروسه ها زمان بیشتری برای بسته شدن نیاز دارند برعکس تردها زمان خیلی کمتری میبرند.۳−ساخت یک پروسه زمانبر تر از ساخت یک ترد است۴− پروسه Context Switching زمان بیشتری میبره تا ترد context switching۵− ارتباط بین تردها سریع از ارتباط بین پروسه ها است۶−پروسه ها به Heavy-weight معروفند از اونجایی که منابع بیشتری میبرند. و ترد ها به light-weight معروفند چون منابع را share میکنند.۷− یک پروسه در یک فضای جداگانه ای در مموری اجرا میشه. ولی تردها در یک فضای مشتری مموری اجرا میشن۸− پروسه های مختلف copies of data, files and codes مختلفی هم دارند ولی ترد ها share میکنن و یکسان هستند۹−مثال: باز کردن یک تب در مرورگر مثال عینی ساخت یک پروسه است و باز کردن چندین تب در مرورگر میتواند مثال ساخت ترد باشد.</description>
                <category>Farchid</category>
                <author>Farchid</author>
                <pubDate>Wed, 11 Aug 2021 22:36:09 +0430</pubDate>
            </item>
                    <item>
                <title>پیاده سازی Mutex در گولنگ</title>
                <link>https://virgool.io/golangpub/%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-mutex-%D8%AF%D8%B1-%DA%AF%D9%88%D9%84%D9%86%DA%AF-pftu6iymqqon</link>
                <description>منبع :)خوب اینجا ما یاد میگیریم چطوری مشکل Race Condition با استفاده از موتکس ها و کانال ها حل کنیم.اول از همه race condition چه کوفتی هست اصلا !؟این مشکل وقتی به وجود میاد که ۲ یا چندین ترد میخواد دسترسی پیدا کنند به دیتاهای توزیع شده و سعی کنند اونارو عوض کنند. خوب نمیشه که فقط یکی میتونه بیاد و یک مقداری تغییر بده اینجاست که conflict شروع میشه.خیلی ساده وقتی یک برنامه وقتی بصورت concurrent داره اجرا میشه. نباید منابع قابل دسترس باشه برای چندین Goroutine.گوروتین چیه !؟گوروتین ها فانکشن ها یا متد هایی هستند که بصورت همزمان با بقیه فانکشن ها و متد ها اجرا میشن. در مقایسه با تردها گوروتین ها بسیار سبک تر و به قولی کم هزینه تر هستند.خوب مثال خیلی ساده ای اینجا شروع میکنیم. فرض کنیم یه کدی داریم که داره مقدار x یک واحد بهش اضافه میکنه و داخل خود x جایگذاری میکنه.x = x + 1تا وقتیکه این کد توسط یک گوروتین قابل دسترس هستش نباید هیچ مشکلی باشه. بیایم بررسی کنیم چرا این کد به مشکل بر میخوره وقتیکه ما چندین گوروتین داریم که دارند بصورت همزمان اجرا میشن. برای اینکه خیلی پیچیده نشده موضوع فرض کنیم ۲ تا گوروتین داریم که دارن کد بالارو همزمان اجرا میکنند.طی ۳ مرحله این کد داره داخل سیستم اجرا میشه مقدار ا فعلی x گرفته میشهمقدار x + 1 محاسبه میشهمقدار محاسبه شده assign میشه به خود xوقتی همه این ۳ مرحله توسط یک گوروتین انجام میشه همه چیز اوکیه و مشکلی نیست.بیاین بررسی کنیم ببینیم چه اتفاقی می افته وقتی ۲ تا گوروتین این کد اجرا میکنن بصورت همزمان. تصویر پایین کاملا نشون میده چه اتفاقی می افته وقتی ۲ تا گوروتین دسترسی پیدا میکنند به x = x +1 بصورت همزمان.ما مقدار اولیه ایکس صفر درنظر گرفتیم. گوروتین ۱ مقدار ایکس میگیره و با ۱ جمعش میکنه و قبل از اینکه بخواد مقدار محاسبه شده به خود ایکس assign کنه گوروتین دوم میاد و مقدار اولیه ایکس که هنوز صفر هستش میگیره و x+1 محاسبه میکنه دوباره سیستم میاد و از موقعیت قبلی گوروتین ۱ شروع میکنه به اجرا شدن و مقدار محاسبه می ریزه داخل ایکس و میشه ۱. حالا گوروتین دوم میاد از ادامه ی مسیر خودش شروع میکنه به اجرا شدن و نهایتا مقدار ایکس بازهم میشه ۱ بعد از اینکه هر دو گوروتین اجرا شدن.حالا یه سناریوی متفاوت بررسی کنیم.همونطور که ملاحظه میکنین گوروتین اول ۳ مرحلرو کامل اجرا میکنه و مقدار ایکس میشه ۱ بعدش گوروتین دوم شروع به اجرا شدن میکنه و بعد از ۳ مرحله مقدار ایکس به ۲ تغییر پیدا میکنه.خوب از این دو سناریو شما فهمیدین که مقدار نهایی ایکس یا ۱ هستش و یا ۲بستگی به نوع Context switching داره، خوب یعنی چی !؟ یعنی اصلا ضمانتی وجود ندارد که ترتیب اجرای اینم گوروتین ها چطوری باشه و اینجاست که ما به Race Condition بر میخوریم :)فقط در یک صورت در سناریو بالا Race Condition میتونه جلوش گرفته بشه اونم وقتیکه یک گوروتین بهش اجازه داده میشه دسترسی داشته باشه به Critical section کد در یک زمان معین. این کار شدنیه با استفاده از موتکس (Mutex)Mutexموتکس مکانیزم قفل کردن برای ما فراهم میکنه و تضمین میکنه که فقط یک گوروتین اجرا کنه کد و از Race Condition جلوگیری خواهد شد.در زبان گو Mutex در پکیج Sync قابل دسترس هستش. دو متد تعریف شده در mutext تحت عنوان Lock و Unlock هر کدی که بین این دو متد اجرا میشه،‌فقط توسط یک گوروتین داره مدیریت میشه بنابراین دیگه Race Condition معنی پیدا نمیکنهmutext.Lock()
x = x + 1
mutex.Unlockاگر یک گوروتین قفل شده باشه و یک گوروتین دیگه بخواد  تلاش کنه برای قفل شدن اتفاقی که می افته اینه که بلاک میشه تا زمانیکه موتکس به حالت unlock دربیاد اون وقت اجازه پیدا میکنه که کارشو انجام بده.برنامه ای با Race Conditionتوی این بخش ما برنامه ای مینویسیم که مشکل Race Condition داره و توی بخش پایین تر راه حل ها رو مطرح میکنیم :)package main 
import (  
    &amp;quotfmt&amp;quot
    &amp;quotsync&amp;quot
    )
var x  = 0  
func increment(wg *sync.WaitGroup) {  
    x = x + 1
    wg.Done()
}
func main() {  
    var w sync.WaitGroup
    for i := 0; i &lt; 1000; i++ {
        w.Add(1)        
        go increment(&amp;w)
    }
    w.Wait()
    fmt.Println(&amp;quotfinal value of x&amp;quot, x)
}در برنامه بالا فانکشن increment مقدار x یک واحد اضافه میکنه و بعدش ()Done صدا میکنه از WaitGroup برای اینکه بگه کارش تموم شده.ما تعداد ۱۰۰۰ تا گوروتین ایجاد کردیم، هر گوروتین بصورت همزمان اجرا میشه و race condition وقتی بوجود میاد که سعی میکنه مقدار ایکس افزایش بده. تعداد زیادی گوروتین دارن تلاش میکنن که به مقدار ایکس دسترسی پیدا کنن !اگر چندین و چند بار شما این برنامه روی سیستم خودتون اجراش کنین هر بار ممکنه یه عددی نمایش بده مثلا941 یا 928 یا 922  و و وحل مشکل با استفاده از موتکس ما اومدین ۱۰۰۰ تا گوروتین ساختیم و اگر هر کدومشون ۱ واحد به ایکس اضافه کنن مقدار نهایی ایکس باید ۱۰۰۰ بشهpackage main  
import (  
    &amp;quotfmt&amp;quot
    &amp;quotsync&amp;quot
    )
var x  = 0  
func increment(wg *sync.WaitGroup, m *sync.Mutex) {  
    m.Lock()
    x = x + 1
    m.Unlock()
    wg.Done()   
}
func main() {  
    var w sync.WaitGroup
    var m sync.Mutex
    for i := 0; i &lt; 1000; i++ {
        w.Add(1)        
        go increment(&amp;w, &amp;m)
    }
    w.Wait()
    fmt.Println(&amp;quotfinal value of x&amp;quot, x)
}میتونین کد اینجا هم اجرا کنینتایپ Mutext از نوع Struct هستش و ما اومدیم متغیر m که صفر هم هستش و از تایپ mutex هست ساختیم و همونطور که میبینین مقدار ایکس که داره تغییر بین فانکشن های Lock و Unlock قرار گرفته و از race condition جلوگیری میشه بخاطر اینکه فقط یک گوروتین اجازه اجرای این کدرو داره در آن واحد.مقدار نهایی الان ۱۰۰۰ خواهد بودیه نکته هست که خیلی مهمه اونم اینه که اینجا go increment(&amp;w, &amp;m) حتما آدرس موتکس باید پاس داده بشه اگر موتکس مقدار پاس داده بشه بجای آدرسش. هر گوروتین یک کپی از موتکس خواهد داشت و race condition لعنتی همچنان پابرجاست.حل مشکل Race Condition با استفاده از کانال هابا استفاده از کانال ها هم ما میتونیم مشکل Race Condition حل کنیم.package main  
import (  
    &amp;quotfmt&amp;quot
    &amp;quotsync&amp;quot
    )
var x  = 0  
func increment(wg *sync.WaitGroup, ch chan bool) {  
    ch &lt;- true
    x = x + 1
    &lt;- ch
    wg.Done()   
}
func main() {  
    var w sync.WaitGroup
    ch := make(chan bool, 1)
    for i := 0; i &lt; 1000; i++ {
        w.Add(1)        
        go increment(&amp;w, ch)
    }
    w.Wait()
    fmt.Println(&amp;quotfinal value of x&amp;quot, x)
}کد میتونین اینجا هم اجراش کنینتوی برنامه بالا ما اومده یک Buffered Channel ساختیم با ظرفیت ۱  و اون کانال به فانکشن increment هم پاس داده شده همونطور که میبینین.این آقای buffered channel استفاده شده تا مطمئن باشیم که فقط یک گوروتین دسترسی به افزایش x داره. و این داره هندل با ارسال مقدار true به کانال و بعد از افزایش ایکس مقدار کانال خونده میشه. خوب طی این مرحله چه اتفاقی می افته ؟ تمامی گوروتین هایی که دارن سعی میکنن توی این کانال بنویسن بلاک میشن تا زمانیکه این مقدار از کانال خونده بشه. جالبه نه !؟ باز هم اینجا فقط به یک گوروتین اجازه داده شد که این عملیات انجام بده و Race Condition هندل شد و مقدار نهایی ۱۰۰۰ میشه.تفاوت بین Mutex و Channelsما مشکل Race Condition با استفاده از این دو بزرگوار حل کردیم ! حالا چطوری تصمیم بگیریم از کدوم کجا استفاده کنیم ؟جواب سوال اینه بستگی داره چه مشکلی شما میخواین حل کنین. اگر مشکل شما بیشتر فکر میکنید با موتکس حل میشه خوب برین اجراش کنین و یا برعکس اگر فکر میکنین با کانال قابل حل شدن شک نکنید.اکثر افرادی که تازه کار هستن در گولنگ مشکلات Concurrency اکثرا با کانال ها برطرف میکنن که خیلی فیچر خفن و باحالیه که این زبان در اختیار ما گذاشته. اما این زبان آپشن های دیگه ای هم مثل موتکس در اختیار ما گذاشته در هر صورت استفاده از هر کدوم هیچ مشکلی بوجود نمیاره.در حالت عادی کانال ها استفاده میشن موقعیکه گوروتین ها نیازمند این هستند که در ارتباط با یکدیگر باشند و موتکس برای موقعی که یک گوروتین فقط باید دسترسی داشته باشه به یک بخش critical کد.در مشکلی که ما حل کردیم موتکس بهترین انتخاب چرا چون هیچ نیازی به ارتباط بین گوروتین ها نبوده.پیشنهاد ما اینه که یک ابزار برای مشکلتون انتخاب کنین و به هیچ وجه سعی نکنین مشکل فیت کنید برای یک ابزار !</description>
                <category>Farchid</category>
                <author>Farchid</author>
                <pubDate>Wed, 11 Aug 2021 00:36:04 +0430</pubDate>
            </item>
                    <item>
                <title>تفاوت بین Mutex و Semaphore در سیستم عامل</title>
                <link>https://virgool.io/Whitenoise/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-%D8%A8%DB%8C%D9%86-mutex-%D9%88-semaphore-%D8%AF%D8%B1-%D8%B3%DB%8C%D8%B3%D8%AA%D9%85-%D8%B9%D8%A7%D9%85%D9%84-s3kfko5pdw8t</link>
                <description>منبع در یک سیستم عامل تعداد خیلی زیاد پروسه وجود داره که آماده هستند برای اجرا شدن در یک زمان خاص. این پروسه ها نیازمند منابعی هستند برای اجرا شدن بنابراین این منابع بین این پروسه ها باید تقسیم بشه.اما یه چیزی هست که باید بهش توجه کنیم اونم اینه که این منابع توزیع شده ولی نباید بصورت همزمان اجرا بشه. مثال عینیش میشه پرینتر،‌فرض کنید یک پرینتر داریم که برای تمای پروسه ها قابل دسترس هستش ولی فقط یک پروسه میتونه دستور پرینت به پرینتر بفرسته و نمیشه همه با هم بصورت همزمان این کارو انجام بدن و این چیزی هستش که ما بهش میگم Process Synchronization که فارسیش خیلی خوب نمیشه ! ولی شاید بتونیم بگیم هم زمانی پروسه ها.Process Synchronization and Critical Sectionفرض کنیم که ما ۲ پروسه داریم که هر دو دارن از متغیر a استفاده میکنند، اول متغیر میخوانند و بعدش مقدارشو تغییرش میدن و آخرش دیتایی را داخل مموری ذخیره میکنند.SomeProccess {          ....          read(a)          a = a + 5           write(a)           .....}همونطوری که در فانکشن مشخصه پروسه میاد اول مقدار a میخونه، بعدش مقدارشو با ۵ جمع میکنه و توی خودش ذخیره میکنه و نهایتا توی مموری ذخیرش میکنه.حالا ما ۲ تا پروسه داریم تحت عنوان P1 و P2 که میخوان اجرا بشن. فرض کنیم مقدار اولیه متغیر a هم ۱۰ هستش.۱− توی این کیس، پروسه P1 کامل اجرا میشه و بعد از اون پروسه P2 اجرا خواهد شد. بنابراین پروسه P1 اول مقدار a میخونه میبینه ۱۰ هستش بعدش میاد توی فانکشن اونو با ۵ جمعش میکنه میشه ۱۵ میریزه داخل خودش و این مقدار توی مموری آپدیت میشه و حالا مقدار a شده 15. حالا پروسه دوم P2 میاد میخونه a میبینه ۱۵ هستش با ۵ جمعش میکنه میشه ۲۰ مقدار a آپدیت میشه و نهایتا مقدار a در مموری میشه ۲۰. توی این مثال مقدار نهایی a شد ۲۰.۲− توی این کیس، بیایم فرض کنیم که پروسه P1 استارت اجراش زده میشه و میاد a میخونه میبینه ۱۰، حالا انتظار داریم بقیه پروسه هم انجام بشه دیگه ولی این وسط یوهو یه اتفاقی می افته اونم Context Switching شاید بپرسین این چه کوفتیه دیگه ! این یه اتفاق جالبیه که توی لایه cpu و kernel اتفاق می افته و اونم اینهه که پروسه یا تسکی که داره اجرا میشه خیلی شیک suspend میشه توسط kernel و روسه بعدی که آماده ی اجرا شدنه توسط cpu فرستاده میشه برای اجرا.حالا P2 درحال اجرا شدنه و P1 توی حالت Waiting هستش و وضعیت P1 هم ذخیره شده. از اونجایی که پروسه P1 نتونسته مقدار a عوض کنه P2 میره مقدار a میخونه و میبینه که ۱۰ هستش. طبق فانکشن تغییرات اعمال میشه و مقدار a به ۱۵ تغییر پیدا میکنه و توی مموری ذخیره میشه. بعد از اجرای P2 پروسه P1 موقعیتش خونده میشه و از همونجا شروع میکنه به ادامه راه خودش. اگر یادتون باشه a خونده شده بود و الان P1 مقدار a توی خودش ۱۰ داره و میره توی فانکشن و ۵ اضافه میشه و مقدار باز هم میشه ۱۵ و توی این مثال مقدار نهایی a شد ۱۵.توی این ۲ تا مثال بالا مقدار نهایی اولی شد ۲۰ و دومی شد ۱۵ چه داستانی پشت این میتونه باشه ؟!پروسه ها دارن از یک ریسورس یکسان استفاده میکنند. متغیر a در روش اول  پروسه P1 اجرا شد و بعدش پروسه P2 ولی در روش دوم پروسه P1 متوقف شد و بعد از اجرای پروسه P2 از همونجایی که متوقف شده بود شروع کرد به اجرا شدن. هر دو پروسه هم از منابع یکسانی برخوردار بودن. این critical section پروسه هستش. باید همگام سازی یا synchronization بین پروسه ها وجود داشته باشه وقتیکه دارن از منابع مشترک استفاده میکنند.منابع مشترک میتونه بین تمامی پروسه ها تقسیم بشه اما فقط یک پروسه اجازه داره در یک زمان از این منابع استفاده کنه. این چیزیه که ما بهش میگیم Process Synchronizationدوتا متد وجود داره برای همگام سازی پروسه ها 1- Mutex2- Semaphoreخوب تک تک بریم سراغ اینا ببینیم چه کوفتی هستن این دوستان :)Mutexموتکس کارش اینه که به پروسه ها اجازه میده از منابع به شکل یکسان استفاده کنند اما فقط در آن واحد یک پروسه اجازه داره از این منابع استفاده کنه. تکنیکی که موتکس داره استفاده میکنه برای هندل کردن critical section بهش میگن متد Lock-Based هر زمانیکه یک پروسه از سیستم درخواستی برای منابع داره، سیستم میاد یک آبجکت موتکس میسازه با یک اسم یا آی دی یونیک و هر وقتیکه پروسه بخواد از منابع استفاده کنه پروسه آبجکت قفل میکنه. بعد از پروسه قفل شدن پروسه اجرا میشه کامل و آبجکت موتکس آزاد میکنه. بعد از اون، پروسه دیگه ای اجازه داره که موتکس خودشو بسازه و ازش استفاده کنه.با استفاده از قفل کردن آبجکت، منبع خاصی که اختصاص داده شده به یک پروسه که هیچ یک از پروسه های دیگه اجازه ندارن از اون منابع استفاده کنند. خوب با این روش خیلی ساده  همگام سازی پروسه ها قابل دسترس هستش.Semaphoreسمافور یک متغیر عددی به اسم S هستش که مقدار اولیه اون تعداد منابع مصرفی  در سیستم برای process synchronization. اون میاد از دو تابع استفاده میکنه برای عوض کردن مقدار S اونم تابع ()wait و ()signal هستش. هر دوی این فانکشن هااستفاده میشن برای تغییر دادن مقدار سمافور اما فقط اجازه میدن یک پروسه تغییر بده مقدار در آن واحد. هر دوی این دو تابع نمیتونن مقدار سمافور در یک زمان با هم تغییر بدن.دو دسته سمافور وجود داره Counting SemaphoreBinary Semaphoreدر Counting Semaphore اول از همه مقدار اولیه سمافور میشه تعداد منابع قابل دسترس. بعد از اون هروقت یک پروسه نیاز داشته باشه به منابع فانکشن ()wait صدا زده میشهو مقدار سمافور یکی کم میشه.پروسه منابع مصرف میکنه و بعدی فانکشن ()signal صدا زده میشه و مقدار سمافور یکی اضافه میشه ! حالا وقتیکه مقدار سمافور به صفر میرسه تمامی منابع توسط پروسه ها گرفته شدنو هیچ منابعی دیگه وجود نداره برای مصرف. بعد اگر بعضی از پروسه های دیگه بخوان از منابع استفاده کنند اونا ناچار هستند که صبر کنند تا منابع برگرده. با این روش ما خیلی ساده Process Synchronization پیاده سازی کردیم.در Binary Semaphore مقدار سمافور میشه ۰ یا ۱. در آغاز مقدار متغیر سمافور ست میشه ۱ و اگر بعضی پروسه ها بخوان از منابعی استفاده کنند فانکشن ()wait صدا زده میشه و مقدار سمافور از ۱ به ۰ تغییر پیدا میکنه. بعد از اینکه پروسه کارش تموم میشه فانکشن ()signal صدا زده میشه و مقدار ست میشه ۱ و منابع آزاد میشن. اگر در آن واحد که مقدار متغیر سمافور ۰ هستش بقیه پروسه ها بخوان از منابع استفاده کنندباید صبر کنند که منابع توسط پروسه قبلی آزاد بشه و با این روش باز هم Process Synchronization پیاده سازی میشه. این روش خیلی شبیه موتکس هستش ولی اینجا عمل قفل شدن پیاده سازی نشده.تفاوت بین موتکس و سمافورتا به اینجای کار ما یاد گرفتیم که موتکس و سمافور چی هستن و احتما خیلی ساده تفاوتشونو متوجه شدین  محض اطمینان یه جمع بندی کوچولو داشته باشیم بد نیست :) جسارت نباشه ;)موتکس مکانیزم قفل شدن استفاده میکنه و اگر پروسه ای بخواد از منابع استفاده کنه اون منابع قفل میکنه، استفاده میشه و بعد آزاد میشه، از اون طرف سمافور میاد از مکانیزم سیگنال استفاده میکنه و متدهای ()wait و ()signal دارن نحوه استفاده از منابع مدیریت میکنند.یک موتکس یک آبجکت هستش اما سمافور یک متغیر از نوع عددی (integer)در سمافور، ما فانکشن های ()wait و ()signal داری، اما در موتکس هیچ فانکشنی وجود نداره برای صدا زدن.یک آبجکت موتکس به چندین تردهای پروسه ها اجازه دسترسی به یک منبع توزیع شده میده اما فقط در یک  زمان مشخص و در آن واحد. از اون طرف سمافور به تردهای پروسه ها اجازه دسترسی به instance های محدودی از منابع میده تا وقتیکه در دسترس هستند.در موتکس قفل شدن و آزاد سازی میتونه توسط یک پروسه انجام بشه. اما مقدار سمافور باید آپدیت بشه توسط هر پروسه ای که نیاز داره به منابع اما فقط یک پروسه اجازه داره.</description>
                <category>Farchid</category>
                <author>Farchid</author>
                <pubDate>Tue, 10 Aug 2021 22:25:00 +0430</pubDate>
            </item>
                    <item>
                <title>همروندی در زبان گو</title>
                <link>https://virgool.io/golangpub/%D9%87%D9%85%D8%B1%D9%88%D9%86%D8%AF%DB%8C-%D8%AF%D8%B1-%D8%B2%D8%A8%D8%A7%D9%86-%DA%AF%D9%88-td5v9appdshx</link>
                <description>در این مقاله میخوایم در مورد همروندی صحبت کنیم، هر جا از این واژه استفاده شده منظور همان Concurrency است.همروندی در زبان گولنگ یکی از مهمترین ویژگی های این زبان به حساب می آید، اما همروندی در این زبان یک راه تفکر است بیشتر تا یک Syntax.برای اینکه به قدرت زبان گو پی ببرید لازم است اول شما روش این زبان را برای کدهایی که بصورت همزمان اجرا میشوند را بررسی کنید.مدلی که زبان گو از آن در همروندی استفاده میکند CSP نام دارد که مخفف Communicating sequential proccesses یا به عبارتی ارتباط متوالی فرآیندها با یکدیگر که در علم پایه کامپیوتر به این مدل ارتباط بین سیستم های همروند میگویند.اما ما اینجا نیستیم که در مورد علم و دانش صحبت کنیم که !!! بنابراین میریم سراغ موارد عملی و جذاب.یه جمله ی معروفی هستش که میگه :Do not communicate by sharing memory; instead, share memory by communicatingخوب این واقعا یعنی چی؟ برای خود من مدت های زیادی طول کشید تا اینو کامل درکش کنم ولی وقتی درکش کردم کارکردن با گولنگ برام خیلی خیلی روان تر شد. آلبرت انیشتن میگه اگر شما نمیتونید خیلی ساده توضیح بدین چیزیرو، شما اونو خیلی خوب متوجه نشدینش! بنابراین تعریف ساده تر اون جمله میشه:Do not communicate by sharing memoryبه عنوان یک برنامه نویس وقتی در مورد همروندی فکر میکنید و نحوه ی اجرای کد اون، بیشترین چیزی که به ذهنتون میرسه تعداد خیلی زیادی از thread هستش که بصورت همزمان دارن بصورت خیلی پیچیده اجرا میشن.بنابراین اکثر مواقع ناچار به اشتراک گذاری دیتا هستین مثل structures, variable, memory و هر چیزی که فکرشو میکنین به thread های مختلف.شما اینکارو انجام میدین با قفل کردن بخشی از مموری که 2 threads نمیتونن همزمان یا بنویسن و یا دسترسی داشته باشند و یا اینکه به امان خدا ولش میکنین تا آزاد بشه و بهترین حالت شاید پیش بیاد و این همون مشکلیه که خیلی از زبانی محبوب باهاش درگیر هستند و باعث اتفاق های عجیبی مثل race condition, memory mangement و اتفاقات غیرقابل پیش بینی که هر شب ممکنه شمارو از خواب بیدار کنه.Instead, share memory by communicatingخوب گو چطوری این کارو انجام میده ؟بجای قفل کردن متغیرها برای اشتراک گذاری مموری، گو به شما این اجازه میده که متغیری را از یک thread به یک thread دیگر ارسال کنید (در حقیقت دقیقا یک thread نیست اما فعلا بیایم اونو یک thread درنظر بگیریم)رفتارپیش فرض برای thread ارسال کننده و همچنین thread دریافت کننده اینه که هر دو صبر میکنند تا value ارسال شده به مقصدش برسه. نکته اینجاست که در زمانی که این دو thread صبر کرده اند باعث میشه یک همگام سازی مناسبی بین thread ها بوجود بیاد.چه مزیتی به ما میده این موضوع؟در واقع شانس خیلی خیلی کمتری وجود داره که مواردی مثل race conditions بخواد پیش بیاد چون هر دو صبر میکنند تا value کاملا ارسال بشه.گولنگ این امکانات بصورت Native و built-in به شما ارایه میکند بدون نصب هیچگونه فریمورک و یا کتابخانه ای خاص.گولنگ همچنین به شما ویژگی دیگه ای هم میده تحت عنوان buffered channel که در بعضی موارد شما نمیخواینهر دو thread قفل و سینک بشن تا زمانی که value ارسال بشه. و فقط زمانی locking اتفاق بی افته که شما تعداد خاصی تعریف کرده باشین برای صبر کردن این thread هانوشتن کد همروند در گولنگخوب چطوری ما میخوایم با روش share by communication model کد خودمونو بنویسیم ؟در گو، یک گو روتین (Goroutine) با خودش این مفهومی که ما دنبالش میگردیمو برای ما میاره !درواقع، اون یک thread نیست، اون یک function هستش که میتونه بصورت همروند با بقیه گوروتین ها در یک فضای مشترک اجرا بشه. تعداد اون ها زیاده در لایه OS و اگر یکی از اون ها قفل بشه بقیه به کار خودشون ادامه میدن. تمام این مراحل سینک کردن و مدیریت مموری در خود زبان داره مدیریت میشه بصورت Native. اینکه میگیم اون ها thread نیستن چون لزوما بصورت پارالل اجرا نمیشنبرای استارت یک گو روتین کافیه از کلمه ی کلیدی &quot;go&quot; استفاده کنین.خط بالا یک گوروتین را که فانکشن ()start اجرا میکنهوجود داره. برنامه اول چاپ میکنه started توجه کنید که خطی که ما چاپ کردیم started بعد از جایی که گوروتین اجرا شده این به ما این نکته نشون میده که بعد از اینکه گوروتین استارت شده برنامه اجراش به خط بعدی رفته. ما یک تایم اوت ست کردیم برای گو روتین خودمون و بعد از رسیدن به اون تایم میبینیم که اجرا میشه و نهایتا finished چاپ میشهحالا چه اتفاقی می افته اگر ما تایم اوت حذف کنیم ؟ اصلا چاپ نشد ! چرا ؟به دلیل اینکه گوروتین اصلی اجراش تموم میشه تا بخواد اون یکی برای خودش برنامه ریزی بکنه.                                             Main Goroutineفانکشن main در پکیج main یک گوروتین اصلی هستش. تمای گوروتین ها شروع میشن از همین main goroutine این گوروتین ها میتوانند چندین گوروتین دیگر را استارت بزنند.گوروتین اصلی بیانگر برنامه اصلی است. وقتی خارج میشه یعنی کل اپلیکیشن خارج شده.گوروتین ها والد و یا فرزندی ندارند. وقتی شما یک گوروتین را استارت میزنید اون کنار بقیه گوروتین ها اجرا میشه.هر گوروتین زمانی تمام میشود که فانکشن اون چیزی را برگرداند. تنها مورد استثنا اینه که تمامی گوروتین ها استاپ میشوند وقتیکه گوروتین اصلی استاپ یا خارج شود.                                   Creating Multiple Goroutinesبرنامه بالا در یک لوپ ۱۰ گوروتین را اجرا میکند و هروقتیکه شما این برنامه را اجرا کنید به شما نتیجه ای مختلف میدهد از اونجایی که گوروتین ها بصورت همروند دارند اجرا میشوند نتیجه قابل انتظاری نمیشود دید.</description>
                <category>Farchid</category>
                <author>Farchid</author>
                <pubDate>Mon, 09 Aug 2021 18:53:50 +0430</pubDate>
            </item>
            </channel>
</rss>