DedSec Project

Ταυτόχρονη εκτέλεση, παραλληλισμός και ακύρωση — DedSec Project

Ταυτόχρονη εκτέλεση και ακύρωση — σωστή απελευθέρωση πόρων Σενάριο και αμετάβλητος κανόνας Μία εφαρμογή γνώσης χωρίς διαδίκτυο μπορεί να ακυρώσει την ευρετηρίαση όταν ο χρήστης κλείσει τη…

Ταυτόχρονη εκτέλεση και ακύρωση — σωστή απελευθέρωση πόρων

Σενάριο και αμετάβλητος κανόνας

Μία εφαρμογή γνώσης χωρίς διαδίκτυο μπορεί να ακυρώσει την ευρετηρίαση όταν ο χρήστης κλείσει τη σελίδα. Οι κοινόχρηστοι πόροι, όπως τα ασύγχρονα κλειδώματα, πρέπει να απελευθερώνονται ακόμη και όταν η ακύρωση φτάνει στη διάρκεια αναμονής. Η ταυτόχρονη εκτέλεση εναλλάσσει εργασίες, ενώ ο πραγματικός παραλληλισμός εκτελεί πράξεις την ίδια στιγμή. Οι συναρτήσεις asyncio συνεργάζονται στα σημεία await, αλλά δεν προστατεύουν αυτόματα κοινόχρηστα μεταβαλλόμενα δεδομένα. Πριν προσθέσεις εργάτες, καθόρισε ιδιοκτησία πόρων και συμπεριφορά ακύρωσης.

Εκτελέσιμο παράδειγμα Python 3.11+

Αποθήκευσε ως cancellation_lab.py και εκτέλεσε python3 cancellation_lab.py. Ένας εργάτης παίρνει το κλείδωμα, δηλώνει ότι ξεκίνησε και περιμένει ένα γεγονός. Ο ελεγκτής ακυρώνει την εργασία και ελέγχει ότι η finally απελευθέρωσε το κλείδωμα. Το παράδειγμα δεν δημιουργεί νήματα, δίκτυο, αρχεία ή χρονοδιακόπτες.

import asyncio

async def do_work(lock, started, unblock, trace):
    async with lock:
        trace.append('entered')
        started.set()
        try:
            await unblock.wait()
            trace.append('finished')
        finally:
            trace.append('cleanup')

async def test():
    lock, started, unblock = asyncio.Lock(), asyncio.Event(), asyncio.Event()
    trace = []
    task = asyncio.create_task(do_work(lock, started, unblock, trace))
    await started.wait()
    assert lock.locked()
    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        pass
    else:
        raise AssertionError('cancellation not delivered')
    assert trace == ['entered', 'cleanup']
    assert not lock.locked()
    async with lock:
        trace.append('reacquired')
    assert trace[-1] == 'reacquired'
    print('PASS async: cancellation, finally cleanup, lock release')

asyncio.run(test())

Τι αποδεικνύει το αποτέλεσμα

Η Task.cancel ζητά ακύρωση και η CancelledError παραδίδεται σε σημείο αναμονής. Κατά την έξοδο εκτελείται η finally και ο διαχειριστής async with απελευθερώνει το κλείδωμα. Ο έλεγχος lock.locked αποδεικνύει το συγκεκριμένο σενάριο, όχι όλες τις πιθανές περιπτώσεις αποκλεισμού ή υλοποιήσεις βιβλιοθηκών. Η ακύρωση μπορεί να συμπέσει χρονικά με την κανονική ολοκλήρωση: οι δοκιμές πρέπει να ξεχωρίζουν τα αποτελέσματα. Η απελευθέρωση του κλειδώματος δεν σημαίνει ότι ανακλήθηκε μία εγγραφή σε βάση ή αρχείο. Η ανθεκτικότητα δεδομένων χρειάζεται χωριστές συναλλαγές ή έλεγχο προσωρινής εγγραφής και ασφαλούς αντικατάστασης.

Στοχευμένες ασκήσεις και διάγνωση

  1. Κάλεσε task.cancel πριν από started.wait και παρατήρησε τι αλλάζει όταν ο εργάτης δεν έχει προλάβει να ξεκινήσει.
  2. Πρόσθεσε δεύτερο εργάτη που περιμένει το ίδιο κλείδωμα και επιβεβαίωσε ότι προχωρά μετά την ακύρωση του πρώτου.
  3. Προκάλεσε συνηθισμένη εξαίρεση μέσα στο κλείδωμα και εξέτασε αν η finally εκτελείται και τότε.
  4. Προσομοίωσε ατελή εγγραφή σε προσωρινό αρχείο και σχεδίασε ανεξάρτητη αποκατάσταση. Η ακύρωση δεν αναιρεί αυτόματα τα byte.

Παραδοτέα: PASS, ακριβής σειρά γεγονότων, διάκριση ταυτόχρονης εκτέλεσης από παραλληλισμό και σχέδιο ανάκτησης μισογραμμένων δεδομένων.

Πρόσθετη τεχνική ανάλυση

Ακύρωση και υπερφόρτωση συναντώνται στον τερματισμό ουράς. Ο παραγωγός που περιμένει πρέπει να μαθαίνει όταν αποτύχουν όλοι οι καταναλωτές. Όρισε αφύπνιση παραγωγών, επιβεβαίωση αποδεκτών εργασιών και διατήρηση ημιτελών μετά επανεκκίνηση. Ο περιορισμένος buffer απαιτεί ρητή πολιτική αντί να κρύβει υπερφόρτωση στη μνήμη.

Περιορισμένες ουρές εργασίας και χειρισμός υπερφόρτωσης