Gesehen
NEW
Programmierung
Google
Gemini 2.5 Flash
VS
OpenAI
GPT-5.4
Implementiere einen sperrfreien konkurrierenden LRU-Cache
Implementiere einen threadsicheren LRU (Least Recently Used) Cache in Python, der gleichzeitig Lese- und Schreibzugriffe unterstützt, ohne für jede Operation einen globalen Lock zu verwenden. Deine Implementierung muss die folgenden Anforderungen erfüllen:
1. **Schnittstelle**: Der Cache muss diese Operationen unterstützen:
- `__init__(self, capacity: int)` — Initialisiere den Cache mit einer gegebenen maximalen Kapazität (positive ganze Zahl).
- `get(self, key: str) -> Optional[Any]` — Gib den mit dem Schlüssel assoziierten Wert zurück, falls er existiert (und markiere ihn als kürzlich benutzt), oder gib `None` zurück, wenn der Schlüssel nicht im Cache ist.
- `put(self, key: str, value: Any) -> None` — Füge das Schlüssel-Wert-Paar ein oder aktualisiere es. Falls der Cache nach der Einfügung die Kapazität überschreitet, entferne das am wenigsten kürzlich verwendete Element.
- `delete(self, key: str) -> bool` — Entferne den Schlüssel aus dem Cache. Gib `True` zurück, wenn der Schlüssel vorhanden war, sonst `False`.
- `keys(self) -> List[str]` — Gib eine Liste aller Schlüssel zurück, die sich derzeit im Cache befinden, geordnet von am kürzesten zuletzt verwendet (most recently used) bis am längsten nicht verwendet (least recently used).
2. **Nebenläufigkeit**: Der Cache muss sicher von mehreren Threads gleichzeitig verwendet werden können. Ziel ist ein Design, das gleichzeitige Lesezugriffe ermöglicht, ohne dass sie sich gegenseitig blockieren, wenn möglich (z. B. durch Leser-Schreiber-Sperren, feinkörnige Sperren oder sperrfreie Techniken). Ein einzelner globaler Mutex, der jede Operation serialisiert, gilt als Ausgangsbasis, ist aber suboptimal.
3. **Korrektheit unter contention**: Bei gleichzeitigen Zugriffen darf der Cache niemals veraltete oder korruptierte Daten zurückgeben, darf niemals seine angegebene Kapazität überschreiten und muss eine konsistente LRU-Reihenfolge beibehalten.
4. **Randfälle, die behandelt werden müssen**:
- Kapazität von 1
- `put` mit einem Schlüssel, der bereits existiert (sollte den Wert aktualisieren und an die Position „am kürzesten zuletzt verwendet“ verschieben)
- `delete` eines Schlüssels, der nicht existiert
- gleichzeitige `put`- und `get`-Operationen auf demselben Schlüssel
- schnelle aufeinanderfolgende Evictions, wenn viele Threads gleichzeitig einfügen
5. **Tests**: Füge eine Testfunktion `run_tests()` hinzu, die die Korrektheit aller Operationen sowohl in Single-Thread- als auch in Multi-Thread-Szenarien demonstriert. Der Multi-Thread-Test sollte mindestens 8 Threads verwenden, die eine Mischung aus `get`, `put` und `delete`-Operationen auf überlappenden Schlüsseln ausführen, und sicherstellen (per Assertions), dass der Cache niemals die Kapazität überschreitet und dass `get` niemals einen Wert für einen Schlüssel zurückgibt, der nie eingefügt wurde.
Gib deine vollständige Implementierung in Python an. Verwende nur die Standardbibliothek (keine Drittanbieter-Pakete). Füge Docstrings und Kommentare hinzu, die deine Nebenläufigkeitsstrategie und etwaige Design-Trade-offs erklären.