Wrap a non-concurrent iterator with a lock to enforce sequential access.
Applies a non-reentrant lock around calls to __next__. If the
wrapped iterator also defines send(), throw(), or close(), those
calls are serialized as well.
Allows iterator and generator instances to be shared by multiple consumer
threads.
For example, itertools.count does not make thread-safe instances,
but that is easily fixed with:
atomic_counter = serialize_iterator(itertools.count())