0

I'm considering using the following design pattern:

from threading import Lock

class FieldsLocker:
    def __init__(self):
        self.lock = Lock()

    def __setattr__(self, name, value):
        if name == 'lock':
            return super().__setattr__(name, value)
        with self.lock:
            print('locked set', name, '=', value)
            return super().__setattr__(name, value)

    def __getattribute__(self, name):
        if name == 'lock':
            return super().__getattribute__(name)
        with self.lock:
            print('locked get', name)
            return super().__getattribute__(name)

class MyClass(FieldsLocker):
    def __init__(self):
        super().__init__()
        self.a = 1
        self.b = 2

o = MyClass()
o.a = o.b

It seems to lock class members whenever they're set and get, it produces the following output:

locked set a = 1
locked set b = 2
locked get b
locked set a = 2

I have 2 questions:

1. Is there any risk of using __setattr__ and __getattribute__ methods for ensuring thread safety of class members in general?

Aside of the fact that a single lock is used for all fields (which is possibly less efficient than using few individual locks for specific members where strictly necessary).

2. Is there any risk of using reusable FieldsLocker parent class from example above?

Aside of the fact that:

  • MyClass may break it by declaring its own self.lock = None
  • the user may forget to put super().__init_() and may want to override __setattr__ and __getattribute__ themselves (and may forget or intentionally not call super() equivalents of these methods).
michalmonday
  • 441
  • 5
  • 11
  • Side question: is there even a point to use a lock when getting items? – michalmonday Dec 10 '21 at 15:36
  • 1
    I think you would find the answers to the question [How to make built-in containers (sets, dicts, lists) thread safe?](https://stackoverflow.com/questions/13610654/how-to-make-built-in-containers-sets-dicts-lists-thread-safe) useful. – martineau Dec 10 '21 at 15:52
  • 1
    To answer your side question: Generally speaking, yes. – martineau Dec 10 '21 at 15:55

0 Answers0