正确使用SyncLock的方法(通常) [英] Proper way to use SyncLock (in general)

查看:586
本文介绍了正确使用SyncLock的方法(通常)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是

This is a follow-up to a previous question regarding locking on two List(Of T) objects. The answer there was helpful but left me with another question.

假设我有一个像这样的函数:

Suppose I have a function like this:

Public Function ListWork() As Integer
  List1.Clear()
  ..Some other work which does not modify List1..
  List1.AddRange(SomeArray)
  ..Some more work that does not involve List1..
  Return List1.Count
End Function

驻留在声明List1的类中.在多线程环境中,我现在知道应该为List1拥有一个私有锁定对象,并在修改或枚举List1时锁定它.我的问题是,我应该这样做吗?

which resides in a class that declares List1. In a multithreaded environment, I now understand that I should have a private locking object for List1 and lock List1 whenever it's modified or enumerated. My question is, should I do this:

Private List1Lock As New Object
Public Function ListWork() As Integer
  SyncLock List1Lock
    List1.Clear()
  End SyncLock
  ..Some other work which does not modify List1..
  SyncLock List1Lock
    List1.AddRange(SomeArray)
  End SyncLock
  ..Some more work that does not involve List1..
  SyncLock List1Lock
    Dim list1Count As Integer = List1.Count
  End SyncLock
  Return list1Count
End Function

或者这个:

Private List1Lock As New Object
Public Function ListWork() As Integer
  SyncLock List1Lock
    List1.Clear()
    ..Some other work which does not modify List1..
    List1.AddRange(SomeArray)
    ..Some more work that does not involve List1..
    Dim list1Count As Integer = List1.Count
  End SyncLock
  Return list1Count
End Function

我猜前一个例子是最优的吗?

I'm guessing that the former example is optimal?

推荐答案

从示例中很难分辨出哪一个是正确的.不过,一些准则/观察可能会帮助您回答问题,或者知道该如何提供其他信息:

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?

在您的示例中,假设您有两个线程.第一个位于.AddRange().Count之间的区域,当第二个线程出现时进入该函数,并获取列表上的锁.

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.

线程1运行更多,击中保护.Count方法的锁,然后进入睡眠状态.同时,线程2清除了列表,然后释放了它的锁,唤醒了线程1,然后线程1获得了该锁.

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.

在这种情况下,当线程1完成构建列表的工作时,线程1将从该函数返回0.然后,由于线程2已经出现并填充了列表,因此列表长度实际上不会为0.

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.

在这种情况下,单个列表操作周围的锁使程序中断,因此在ClearCount调用之间使用一个锁是更有意义的.

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.

简而言之,多线程是介绍与种族条件有关的一类细微错误的好方法. ,通常会导致 Heisenbugs .

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.

这篇关于正确使用SyncLock的方法(通常)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆