Critical section is a code block that cannot be executed by more than one process/thread at a time, which is why critical sections are expensive and can lead to a performance "bottle neck" at a specific flow.
Critical sections must be as short, simple (if possible), and efficient as possible.
For example, let's examine the following code block, which generates a new UUID for a shared object:
with self._mutex:
# start of lock
try:
self._action.id = str(uuid.uuid4())
self._logger.trace("action generated, action_id={action_id}".format(action_id=self._action.id))
except BaseException as err:
self._logger.error(err,"failed to generate uuid")
# end of lock
I did three common mistakes here:
- try & catch, ok, I admit it, probably not a common mistake since no one will put a try & catch that could be outside of a critical section inside of it without a good reason
- logging inside a critical section. Usually, logging is an expensive IO operation which could have be done outside
- generating the UUID inside the critical section
Here is the another code block which does the exact same thing, just without the three mistakes:
try:
action_id = str(uuid.uuid4())
with self._mutex:
# start of lock
self._action.id = action_id
# end of lock
self._logger.trace("action generated, action_id={action_id}".format(id=action_id))
except BaseException as err:
self._logger.error(err,"failed to generate uuid")
When you are using lock remember that is purpose is to avoid more than one thread access shared resources at the same time
Top comments (0)