דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. סדר התשובות בלולאה אסינכרונית

סדר התשובות בלולאה אסינכרונית

מתוזמן נעוץ נעול הועבר תכנות
10 פוסטים 3 כותבים 232 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • nigunN מנותק
    nigunN מנותק
    nigun
    כתב ב נערך לאחרונה על ידי nigun
    #1

    כמו שאמרו כאן כמה חברים שאני אצטרך די מהר להשתמש בקוד אסינכרוני
    זה הגיע יותר מהר ממה שחשבתי
    אני מנסה לבדוק איך הAPI שלי (שכתוב בPHP) מחזיק במספר קריאות במקביל (למה זה אמור בכלל לעשות בעיה , זה נושא בפני עצמו)
    אז בניתי סקריפט בגו שישלח בקשה לשרת דרך HTTP
    ועשיתי לולאה של קריאות אסינכרוניות (דהיינו שקורא לפונקציה ולא מחכה לתשובה ומפעיל את הפונקציה שוב )
    עד עכשיו הכל טוב ויפה אבל לא תמיד הקריאה הראשונה מסתיימת לפני השנייה
    ואני לא יודע מתוך התשובות שקיבלתי מה היה סדר הקריאות
    ניסיתי לכתוב שידפיס בסוף הפונקציה את המספר של הלולאה הנוכחית
    אבל תמיד זה יוצא לי בסדר הפוך (דהיינו תוצאה 2 ואז 1)
    האם אני עשיתי נכון ופשוט משום מה הקריאה השניה חוזרת לפני הראשונה או שלא הבנתי נכון איך זה עובד?
    אני יצרף פה את הקוד שאמנם כתוב בגו אבל אולי זה יעזור להבין את השאלה

    
    package main
    
    import (
        "strings"
        "os"
        "fmt"
    	"io/ioutil"
    	"net/http"
    )
    
    func postto(s int, c chan int) {
    body := strings.NewReader(`phone=0523456789&amount=3`)
    
    
    req, err := http.NewRequest("POST", "http://www.host.com/test.php", body)
    
    if err != nil {
            
    }
    
    
    
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
    }
    defer resp.Body.Close()
      contents, err := ioutil.ReadAll(resp.Body)
            if err != nil {
                fmt.Printf("%s", err)
                os.Exit(1)
            }
            fmt.Printf("%s\n", string(contents))
           fmt.Println(s)
    c <- s
        }
      func main() {
                 var b int = 3
       var a int
    	c := make(chan int)
       for a < b {
          a++
              
    
          go postto(a,c)
       } 
     x, y := <-c, <-c 
    
    	fmt.Println(x, y)
    }
    
    
      
    
    
    

    מייל: nigun@duck.com

    תגובה 1 תגובה אחרונה
    0
    • nigunN מנותק
      nigunN מנותק
      nigun
      כתב ב נערך לאחרונה על ידי
      #2

      עדכון:עכשיו הוספתי לתחילת הפונקציה

          now := time.Now()
      
            unixNano := now.UnixNano()                                                                      
               umillisec := unixNano / 1000000
      

      שזה אמור להגדיר משתנה לזמן כרגע במילי שניות
      ובסוף הפונקציה ליד איפה שהגדרתי שידפיס את מספר הלולאה
      הגדרתי שידפיס את משתנה הזמן שהוגדר בתחילת הפונקציה

       fmt.Println("(correct)Millisecond : ", umillisec) 
      

      ותוצאה היא

      OK
      2
      (correct)Millisecond :  1561995505989
      OK
      1
      (correct)Millisecond :  1561995505991
      

      OK זה התשובה מהשרת שלי
      אבל למרבה הפלא בזמן כתוב קודם את הקריאה הראשונה ובמספר הלולאה את השניה
      אז כנראה פיספסתי כאן משהו

      מייל: nigun@duck.com

      י תגובה 1 תגובה אחרונה
      0
      • י מנותק
        י מנותק
        יוסף בן שמעון
        השיב לnigun ב נערך לאחרונה על ידי יוסף בן שמעון
        #3

        @nigun

        1. אתה יכול להתפטר מהשורות המיותרות האלה
        if err != nil {
                
        }
        

        אם בהשמה תכתוב כך:

        resp, _ := http.DefaultClient.Do(req)
        
        

        במקום לכתוב err כותבים קו תחתון וזה פוטר אותך מלהשתמש במשתנה הזה.

        1. יש לך טעות בלולאה, אתה רצית 2 קריאות אבל אתה בעצם מריץ לולאה של 3 קריאות כי a מתחיל מאפס ונגמר ב 3, הסיבה שאתה לא רואה 3 תוצאות כנראה בגלל שהפונקציה main מתה לפני שהקריאה השלישית מתסיימת. תוסיף בסוף הפונקציה השהייה כזו:
        time.Sleep(10 * time.Second)
        

        ותבדוק אם זה משנה את התמונה

        לגופה של שאלה, לא התעמקתי לגמרי בקוד שלך, אבל זה נשמע לי הגיוני לגמרי שקריאה שניה מגיעה לפני קריאה ראשונה, זה תלוי בהרבה פרמטרים, המשתנה של הזמן לא מעיד על שום דבר כי שני המשתנים מאותחלים כמעט במקביל כי שתי הפונקציות נקראות אחת אחרי השניה ברצף וזה מאותחל מיד עם אתחול הפונקציה

        nigunN תגובה 1 תגובה אחרונה
        4
        • nigunN מנותק
          nigunN מנותק
          nigun
          השיב ליוסף בן שמעון ב נערך לאחרונה על ידי nigun
          #4

          @יוסף-בן-שמעון

          1. הורדתי את השורות של הerr (זה לא הבעיה אבל הקוד יותר נקי)
          2. הלולאה רצה 2 פעמים כי התנאי הוא a<2 ולא a<=2
            לצורך ביטחון הגדרתי Sleep ל10 שניות
            ועדיין מחזיר רק שתי קריאות

          לגופו של עניין אין לי בעיה שיחזרו בסדר שונה
          אבל אני רוצה לדעת מה הסדר של הקריאות

          המשתנה של זמן לכאורה אמור להצביע על איזה קריאה נעשתה קודם
          כי יש הבדל של חלקיק שנייה בין קריאה לקריאה
          וגם המשתנה a אמור להיות בלולאה הראשונה 1 ובשניה 2
          אבל זה עובד בדיוק הפוך משום מה

          עכשיו הרצי את הקוד פעמים וכל פעם חזר בסדר שונה
          אין לי בעיה עם זה אבל מה קרה בכל פעם
          שים לב שגם המשתנים x y מושפעים מסדר התשובות (כי הם מקבלים את הערך מs)

          root@scw-vibrant-bhabha:~#  go run /root/go/src/curl/main2.go
          OK
          2
          (correct)Millisecond :  1562049086784
          OK
          1
          (correct)Millisecond :  1562049086787
          2 1
          root@scw-vibrant-bhabha:~# go run /root/go/src/curl/main2.go
          OK
          1
          (correct)Millisecond :  1562049526808
          OK
          2
          (correct)Millisecond :  1562049526807
          1 2
          

          מייל: nigun@duck.com

          yossizY תגובה 1 תגובה אחרונה
          0
          • yossizY מנותק
            yossizY מנותק
            yossiz
            השיב לnigun ב נערך לאחרונה על ידי yossiz
            #5

            @nigun ברגע שאתה קורא לפונקציה ע"י מילת המפתח go, הפסדת כל שליטה על סדר הפעולות, ה-scheduler של גו חופשי לעשות מה שבא לו. אין לך זכות לצפות לשום סדר דטרמיניסטי.

            אתה כן יכול להניח שה-scheduler לא סתם משחק משחקים איתך בשביל הכיף... ואם תעמיק בקוד של ה-scheduler תוכל להבין מה קורה, אבל אסור לך לסמוך על סדר מסויים.

            פעם עניתי על שאלה דומה, וניסיתי לנתח איך ה-scheduler מבצע תוכנה מסויימת עיין כאן. אולי התשובה שם יעזור לך להבין מה קורה פה.

            (בלי להכיר כל כך את השפה, אני די בטוח שבמקרה שחייבים סדר מסויים יש מבנים בתוך השפה שתוכל להשתמש בהם כדי לסנכרן סדר הפעולות, אבל הרי לא עשית את זה)

            📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

            nigunN תגובה 1 תגובה אחרונה
            4
            • nigunN מנותק
              nigunN מנותק
              nigun
              השיב לyossiz ב נערך לאחרונה על ידי nigun
              #6

              עכשיו ניסיתי לוותר לגמרי על האזנה לערוץ

               x, y := <-c, <-c 
              
              	fmt.Println(x, y)
              

              ולהשתמש רק בפונקצית שינה
              ועכשיו המספר לולאה כן לפי הסדר הזמנים של הקריאות
              הנה התשובות שקיבלתי
              הראשון זה בלי Sleep
              והשני עם Sleep ובלי האזנה לערוץ

              root@scw-vibrant-bhabha:~# go run /root/go/src/curl/main2.go
              OK
              1
              (correct)Millisecond :  1562065593494
              OK
              2
              (correct)Millisecond :  1562065593491
              1 2
              root@scw-vibrant-bhabha:~# go run /root/go/src/curl/main2.go
              OK
              2
              (correct)Millisecond :  1562065640343
              OK
              1
              (correct)Millisecond :  1562065640341
              

              זה נראה שבשני הפעמים הקריאה השניה חוזרת לפני הראשונה
              אבל לפחות בפעם השניה כתוב לי שזה הקריאה השניה ולא הראשונה
              וזה נראה נכון כי 1562065640343 זה אחרי 1562065640341
              (אני מקווה שאני כותב ברור ולא קשקושים לא מובנים)

              מייל: nigun@duck.com

              yossizY תגובה 1 תגובה אחרונה
              0
              • yossizY מנותק
                yossizY מנותק
                yossiz
                השיב לnigun ב נערך לאחרונה על ידי
                #7

                @nigun לא הבנתי לְמֵה אתה חותר.
                אם אתה רוצה להדפיס שורה ולדעת איזה פונקציה כותב את זה, תדפיס באותה שורה גם את המספר של הקריאה.
                לגבי סדר הפעולות, אתה יכול לסמוך על זה שהסדר בתוך הפונקציה נשמר, אבל לא תוכל לסמוך על שום סדר בין-פונקציאלי.
                אאל"ט, גם מילת המפתח go, לא מריץ את הפונקציה, אלא שם את הפונקציה בתור להרצה מתישהו. אתה יכול לסמוך שהקריאה הראשונה הושם בתור לפני השניה, אבל אתה לא יכול לסמוך על שסביבת ההרצה החליטה להתחיל את הרצת הראשונה לפני השניה.

                📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

                nigunN תגובה 1 תגובה אחרונה
                1
                • nigunN מנותק
                  nigunN מנותק
                  nigun
                  השיב לyossiz ב נערך לאחרונה על ידי nigun
                  #8

                  @yossiz
                  אני רוצה לדעת את מספר קריאה
                  ומשום מה זה לא נראה שזה כותב את המספר קריאה האמיתי
                  הדרך שאני מנסה לבדוק האם זה המספר קריאה הנכון
                  אני מדפיס בנוסף את זמן הקריאה
                  ומשום מה זה כותב קריאה 1 בשניה 343.. וקריאה 2 בשניה 341...
                  וכל זה קורה רק אם אני מחכה לתשובה מהערוץ בסוף הסקריפט
                  אבל אם אני סתם מחכה בסוף הסקריפט 10 שניות
                  אז יוצא לי קריאה 1 בשניה 341.. וקריאה 2 בשניה 343...
                  אם זה היה חד פעמי הייתי אומר שבדיוק ככה יצא שלפעמים הקריאה הראשונה מתחילה אחרי השניה
                  אבל זה כל הזמן חוזר בסדר הזה (גם אם הקריאה השניה חוזרת ראשונה וגם להיפך)

                  אולי אם אני ישים את בשורה אחת זה יהיה יותר מובן

                  OK
                  (correct)Millisecond :  1562077651112 at 1
                  OK
                  (correct)Millisecond :  1562077651110 at 2
                  

                  מייל: nigun@duck.com

                  yossizY תגובה 1 תגובה אחרונה
                  0
                  • yossizY מנותק
                    yossizY מנותק
                    yossiz
                    השיב לnigun ב נערך לאחרונה על ידי yossiz
                    #9

                    @nigun אמר בסדר התשובות בלולאה אסינכרונית:

                    ומשום מה זה לא נראה שזה כותב את המספר קריאה האמיתי

                    במושכל ראשון אין כל סיבה לחשוש שהפלט לא נכון.

                    הדרך שאני מנסה לבדוק האם זה המספר קריאה הנכון
                    אני מדפיס בנוסף את זמן הקריאה

                    זו לא דרך נכונה לבדוק תקינות הפלט מכיון שא"א להניח שום הנחות בנוגע להתנהגותו של ה-scheduler בגו, ואתה מסתמך על ההנחה המוקדמת שפונקציה שביקשת את הרצתה ראשון באמת תרוץ ראשון, מה שכנראה תלוי בהמון משתנים שקשה להבינם בלי לקרוא את הקוד של ה-scheduler.
                    בכל מקרה, קוד שמסתמך על איזשהו התנהגות שהוא מצפה מה-scheduler הוא קוד לא נכון.

                    אני יודע שלא עניתי על שאלתך "למה זה רץ בסדר זה?" אבל אופתע אם יש תשובה פשוטה לשאלה הזאת.
                    תשובה חלקית יכולה להיות שהחלטות ה-scheduler מושפעות מהצפי שלו לגבי איזה goroutine ישפיע על הזרימה החלקה של המשך הקוד. כאשר אתה קורא sleep אז סביבת ההרצה "יודע" שאתה לא זמין לעוד הרבה זמן, וזה משפיע על החלטותיה לגבי על איזה ליבה ואיזה thread לתזמן את ה-goroutines שמחכים בתור. וזה משפיע על התזמון של ההרצות.

                    יש לך פה בלוג ב-3 המשכים על נושא התזמון בגו.
                    https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part1.html
                    https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part2.html
                    https://www.ardanlabs.com/blog/2018/12/scheduling-in-go-part3.html

                    אחרי זה, תוכל לקרוא את קוד המקור של רכיב ה-scheduler פה: https://golang.org/src/runtime/proc.go (להתראות בעוד חודש...) 🙂

                    📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

                    nigunN תגובה 1 תגובה אחרונה
                    3
                    • nigunN מנותק
                      nigunN מנותק
                      nigun
                      השיב לyossiz ב נערך לאחרונה על ידי
                      #10

                      @yossiz
                      מצאתי כאן הסבר למה זה רנדומאלי
                      אבל למען האמת לא הבנתי את ההסברים

                      מייל: nigun@duck.com

                      תגובה 1 תגובה אחרונה
                      1

                      בא תתחבר לדף היומי!
                      • התחברות

                      • אין לך חשבון עדיין? הרשמה

                      • התחברו או הירשמו כדי לחפש.
                      • פוסט ראשון
                        פוסט אחרון
                      0
                      • דף הבית
                      • קטגוריות
                      • פוסטים אחרונים
                      • משתמשים
                      • חיפוש
                      • חוקי הפורום