def start_readout(self, *args, **kwargs):
<EOL>callback = kwargs.pop('<STR_LIT>', self.handle_data)<EOL>errback = kwargs.pop('<STR_LIT>', self.handle_err)<EOL>reset_rx = kwargs.pop('<STR_LIT>', True)<EOL>reset_fifo = kwargs.pop('<STR_LIT>', True)<EOL>fill_buffer = kwargs.pop('<STR_LIT>', False)<EOL>no_data_timeout = kwargs.pop('<STR_LIT>', None)<EOL>enabled_fe_channels = kwargs.pop('<STR_LIT>', self._enabled_fe_channels)<EOL>if args or kwargs:<EOL><INDENT>self.set_scan_parameters(*args, **kwargs)<EOL><DEDENT>if self._scan_threads and self.current_module_handle not in [t.name for t in self._scan_threads]:<EOL><INDENT>raise RuntimeError('<STR_LIT>' % t.name)<EOL><DEDENT>if self._scan_threads and self.current_module_handle in self._curr_readout_threads:<EOL><INDENT>raise RuntimeError('<STR_LIT>')<EOL><DEDENT>with self._readout_lock:<EOL><INDENT>self._curr_readout_threads.append(self.current_module_handle)<EOL><DEDENT>self._starting_readout_event.clear()<EOL>while not self._starting_readout_event.wait(<NUM_LIT>):<EOL><INDENT>if self.abort_run.is_set():<EOL><INDENT>break<EOL><DEDENT>with self._readout_lock:<EOL><INDENT>if len(set(self._curr_readout_threads) & set([t.name for t in self._scan_threads if t.is_alive()])) == len(set([t.name for t in self._scan_threads if t.is_alive()])) or not self._scan_threads:<EOL><INDENT>if not self.fifo_readout.is_running:<EOL><INDENT>self.fifo_readout.start(fifos=self._selected_fifos, callback=callback, errback=errback, reset_rx=reset_rx, reset_fifo=reset_fifo, fill_buffer=fill_buffer, no_data_timeout=no_data_timeout, filter_func=self._filter, converter_func=self._converter, fifo_select=self._readout_fifos, enabled_fe_channels=enabled_fe_channels)<EOL>self._starting_readout_event.set()<EOL><DEDENT><DEDENT><DEDENT><DEDENT>
Starting the FIFO readout.

        Starting of the FIFO readout is executed only once by a random thread.
        Starting of the FIFO readout is synchronized between all threads reading out the FIFO.