Proper way to use SyncLock (in general)

让人想犯罪 __ 提交于 2019-12-05 04:27:42

From the examples, it's hard to tell which one is correct, if either is. A few guidelines/observations though that might help you answer your question, or know what to provide for additional information:

First things first, do you have to synchronize? Would it make more sense for each thread to have an instance of this class? If each instance is local to the thread, and is only modified and used on that thread, you don't need locking.

If the purpose of this class and utilizing threads is for parallel processing of a larger data set, it might make more sense for the main thread to divide up the task in some logical way, and then wait for the worker threads to complete. In this case, instead of managing threads on your own, look into the ThreadPool and wait handles. Most of the dirty work is done for you then.

About synchronization/locking in general: If your operation was interrupted between steps, would the data be consistent/valid?

In your example, say you have two threads. The first is in the area between .AddRange() and .Count, when the second thread comes along enters the function, and acquires the lock on the list.

Thread 1 runs a bit more, and hits the lock guarding the .Count method, and goes to sleep. Thread 2 in the meantime clears the list and then releases its lock, waking Thread 1 up, which then acquires the lock.

In this case, Thread 1 will have 0 returned from this function, when work was done by thread 1 to build the list. And then, the list length won't really be 0, since thread 2 has come along and filled the list.

In this case, the locks around the individual list operations break the program, so it makes more sense to have one lock surrounding between Clear and the Count call.

In short, multi-threading is a good way to introduce a whole class of subtle bugs relating to Race Conditions, that often result in Heisenbugs.

It is often wise to avoid threads when you can. If you can't, try to arrange your workload in ways that require minimal synchronization (e.g. giving the thread a set of data at the start, then waiting for it to signal completion, such as with the thread pool example linked). If you can't do that, then tread carefully, and always ask yourself "What will happen if two threads run in this area".

Hopefully this helps arm you for future adventures in multi-threaded code.

"It depends". The two examples have different semantics.

In the latter example the entire set of operations is atomic with respect to the lock. While in the former example access to the list is guarded in lock, but the entire set of operations can't be (correctly) viewed as atomic (with respect to the lock).

Imagine what would/could happen in terms if operation/thread interleaving if ListWork was invoked upon the same object by different threads.

Happy coding.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!