use thread-local storage instead of lock