Did I overuse / underuse threading locks in my custom list class?
While it looked like at first glance that you were missing quite a few from the normal list methods:

&gt;&gt;&gt; dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']


Inheriting from collections.MutableSequence takes care of most of them (by using internally the re-implemented methods instead of the C methods).

&gt;&gt;&gt; l = ThreadSafeList([3, 2, 1, 1])


A few are still missing, though:

&gt;&gt;&gt; l.sort()
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
AttributeError: 'ThreadSafeList' object has no attribute 'sort'

&gt;&gt;&gt; l = l + [1]
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: unsupported operand type(s) for +: 'ThreadSafeList' and 'list'

&gt;&gt;&gt; l = l + l
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: unsupported operand type(s) for +: 'ThreadSafeList' and 'ThreadSafeList'

&gt;&gt;&gt; l = l * 3
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: unsupported operand type(s) for *: 'ThreadSafeList' and 'int'


Although, there seem to be work-arounds for all of them, if changing mutating and non-mutating is fine:

&gt;&gt;&gt; l = ThreadSafeList(sorted(l))
&gt;&gt;&gt; l.extend([1])
&gt;&gt;&gt; l.extend(l)
&gt;&gt;&gt; l = ThreadSafeList(list(l) * 3)


Note that there is no way to add these lists without mutating them.

Otherwise, I see only one style-issue:

The output of repr should ideally include the class, so that eval(repr(obj)) returns a copy of the instance. You can define it like this:

def __str__(self):
    return str(self._list)

def __repr__(self):
    return "{self.__class__.__name__}({self._list})".format(self=self)


The latter can be slightly simplified in Python 3.6, using f-strings:

def __repr__(self):
    return f"{self.__class__.__name__}({self._list})"