Use the lock to protect shared mutable state during mutations, but avoid holding it for read-side convenience/field-by-field getters.
Rules
logs[], updates[], notifications[]).Example pattern (commit under lock, transform outside)
def update_item(self, *, no: int, heading: str | None, content: str | None):
# Preprocess outside the lock
if heading is not None:
new_heading = _truncate_heading(self._mask_recursive(heading))
if content is not None:
item_type = self.logs[no].type # or pass in required type explicitly
new_content = _truncate_content(self._mask_recursive(content), item_type)
with self._lock:
item = self.logs[no]
if heading is not None:
item.heading = new_heading
if content is not None:
item.content = new_content
self.updates.append(item.no)
Applying this standard will reduce lock contention, prevent unnecessary refactors tied to read-side locking, and still keep shared writes thread-safe.
Enter the URL of a public GitHub repository