Sobes.tech
Middle

რატომ წარმოიქმნება თხელი რგოლების რბოლა და რა მეთოდები არსებობს მათთან ბრძოლისთვის?

sobes.tech AI

პასუხი AI-სგან

რეგულაციების (race conditions) წარმოშობა ხდება, როდესაც რამდენიმე ნაკადი ერთდროულად მიმართავს საერთო ცვლილებადი მონაცემებს, და მათი შესრულების შედეგი დამოკიდებულია მათი შესრულების წესზე. ეს ხდება, რადგან ოპერაციული სისტემა ნებისმიერ დროს შეუძლია გადართოს ნაკადებს, INTERRUPTING მათ შესრულებას.

მკლავობის გზები:

  • სინქრონიზაცია: სინქრონიზაციის პრიმიტივების გამოყენება, რათა უზრუნველყოს ექსკლუზიური წვდომა საერთო რესურსებზე.

    • synchronized საკვანძო სიტყვა: გამოიყენება მეთოდებზე ან კოდის ბლოკებზე. ბლოკავს წვდომას ობიექტზე ან კლასზე სხვა ნაკადებისთვის, სანამ მიმდინარე ნაკადი არ დასრულდება სინქრონიზებულ ბლოკის/მეთოდის შესრულება.

      // სინქრონიზებული მეთოდი
      public synchronized void updateData(int newValue) {
          // ... საერთო მონაცემების განახლება
      }
      
      // კოდის ბლოკის სინქრონიზაცია
      public void processData() {
          synchronized (this) { // ან სხვა მონიტორის ობიექტი
              // ... წვდომა საერთო მონაცემებზე
          }
      }
      
    • ლოკები (Lock): უზრუნველყოფს უფრო მოქნილ კონტროლს სინქრონიზაციის მიმართ, შედარებით synchronized-ის.

      import java.util.concurrent.locks.Lock;
      import java.util.concurrent.locks.ReentrantLock;
      
      private final Lock dataLock = new ReentrantLock();
      
      public void safeUpdateData(int newValue) {
          dataLock.lock(); // ლოკის დაჭერა
          try {
              // ... საერთო მონაცემების განახლება
          } finally {
              dataLock.unlock(); // ლოკის გათავისუფლება
          }
      }
      
  • ატომური ცვლადები (Atomic...): უზრუნველყოფს ნაკადების უსაფრთხო ოპერაციებს პრიმიტიული ტიპების მიმართ, აშკარა ლოკირების გარეშე. გამოიყენება მარტივი ოპერაციებისათვის (ინკრემენტი, შედარება და გაცვლა).

    import java.util.concurrent.atomic.AtomicInteger;
    
    private final AtomicInteger counter = new AtomicInteger(0);
    
    public void incrementCounter() {
        counter.incrementAndGet(); // ატომური გაზრდა
    }
    
  • ნაკადების უსაფრთხო კოლექციები: გამოყენება სპეციალური კოლექციების java.util.concurrent პაკეტიდან (მაგალითად, ConcurrentHashMap, CopyOnWriteArrayList), რომლებიც განკუთვნილია მრავალნაკადიანი წვდომისთვის.

    import java.util.concurrent.ConcurrentHashMap;
    import java.util.Map;
    
    private final Map<String, Integer> safeMap = new ConcurrentHashMap<>();
    
  • შეუვალ (Immutable) ობიექტები: თუ მონაცემები არ იცვლება შექმნის შემდეგ, მათზე უსაფრთხოდ შეიძლება წვდომა ჰქონდეს რამდენიმე ნაკადს, სინქრონიზაციის გარეშე.

  • ThreadLocal ნაკადის ადგილობრივი ცვლადები: თითოეულ ნაკადს მიენიჭება საკუთარი ასლი ცვლადის, რაც გამორიცხავს კონკურენციას წვდომისთვის.

    private final ThreadLocal<Integer> threadId = new ThreadLocal<>();
    
    public void setThreadId() {
        threadId.set(Thread.currentThread().getId());
    }
    
    public int getThreadId() {
        return threadId.get();
    }
    
  • მართებული არქიტექტურის დიზაინი: საერთო ცვლილებადი მონაცემების მინიმალიზაცია და ასინქრონული მიდგომების ან შეტყობინებების გადაცემა ნაკადებს შორის შეიძლება შემცირდეს რბოლების ალბათობა.