C# 多线程 - 告诉等待进程第一个进程已完成使用锁定代码?

发布于 2024-08-11 01:06:06 字数 107 浏览 3 评论 0 原文

据我所知,在开发多线程应用程序时,您必须使用监视器或锁来同步对共享内存的访问。

问题

如何告诉等待进程(proc2)使用锁定代码块(proc1)的进程已完成使用该代码?

I understand that when developing multithreaded applications you must synchronize access to shared memory using either, for instance, a monitor or a lock.

QUESTION

How do you tell the waiting process(proc2) that the process using the locked code block (proc1) has finished using the code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

铜锣湾横着走 2024-08-18 01:06:06

您是在谈论真正的操作系统进程,还是只是进程中的任务?

如果只是流程中的任务,您通常只需让锁为您完成工作。第二个任务尝试获取第一个任务当前拥有的锁,但只是阻塞。当第一个任务释放锁时,第二个任务会自动解锁。

如果您希望第二个线程可以选择先执行其他工作,您可以使用 Monitor.TryEnter 代替 - 尽管这稍微麻烦一些。

如果您想等待,但您有比锁定更复杂的要求,那么可能需要使用 Monitor.Pulse/PulseAll/Wait。有关示例,请参阅此页面的后半部分。

如果您实际上谈论的是进程,那么您需要使用系统范围的结构,例如互斥体。它们比进程内 .NET 监视器“更重”,但允许进程间协调。

Are you talking about real operating system processes, or just tasks within a process?

If it's just tasks within a process, you typically just let locks do the work for you. The second task tries acquire the lock that the first task currently owns, and just blocks. When the first task releases the lock, the second task is automatically unblocked.

If you want to the second thread to have the option of doing other work first, you could use Monitor.TryEnter instead - although that's slightly more fiddly.

If you want to wait but you have more sophisticated requirements than just locking, then Monitor.Pulse/PulseAll/Wait are probably called for. See the second half of this page for an example.

If you're actually talking about processes then you'll need to use a system-wide structure such as a Mutex. These are "heavier" than in-process .NET monitors, but allow for inter-process coordination.

迷路的信 2024-08-18 01:06:06

另一个进程通常被阻塞,等待获取锁。当第一个进程释放它时,第二个进程就可以抓住它。

换句话说,在典型的场景中,您不会“告诉”另一个线程运行,而是停止阻止它运行。

(在某些情况下,您确实希望告诉线程继续运行,通常由 AutoResetEvent 或 ManualResetEvent 处理)

The other process is usually blocked, waiting to grab the lock. When your first process releases it, the second process can grab it.

In other words, in a typical scenario, you don't 'tell' the other thread to go, instead you stop preventing it from going.

(There are scenarios where you do want to tell a thread to go, usually handled by a AutoResetEvent or a ManualResetEvent)

究竟谁懂我的在乎 2024-08-18 01:06:06

为此,您需要使用 C# 中提供的各种同步对象。可用同步对象的一些示例是 System.Threading.Mutex< /a>, System.Threading.Semaphore, System.Threading.ManualResetEventSystem.Threading.AutoResetEvent(这不是详尽的列表,但这是基础)。您需要的确切同步对象取决于您的特定需求。

互斥锁可能是最简单的使用方式,所以我将举个例子。假设我有两个函数在两个不同的线程中运行(我将坚持使用您自己的示例,proc1 和 proc2)。两个函数都需要访问同一个变量 foo。在每个访问 foo 的函数中,您需要首先“锁定”互斥体。然后做任何你需要做的事情,然后解锁。

例如:

class bar
{
  private int foo;
  private System.Threading.Mutex lock = new System.Threading.Mutex;

  public void proc1()
  {
    lock.WaitOne();

    // do stuff to foo

    lock.ReleaseMutex();
  }

  public void proc2()
  {
    lock.WaitOne();

    // do stuff to foo

    lock.ReleaseMutex();
  }
};

使用该方法,proc1将执行。它会尝试“抓住”互斥锁(锁)。如果互斥锁已被占用,proc1 将进入睡眠状态,直到互斥锁被另一个线程“释放” - proc1 将坐下来等待,不执行任何操作(并且不占用任何 CPU 周期!),直到互斥锁被释放。然后它会锁定它并做它的事情。在 proc1 完成使用互斥锁之前,其他线程都无法获取该互斥锁。

另一种选择是使用事件。 C# 提供两种类型的事件 - 手动重置和自动重置。我将在我的示例中使用手动重置事件。

class bar
{
  private System.Threading.ManualResetEvent event = new System.Threading.ManualResetEvent;

  public void proc1()
  {
    // do stuff

    event.Set();
  }

  public void proc2()
  {
    event.WaitOne();
    event.Reset();

    // do stuff
  }
};

在此示例中,当 proc2 运行时,它会在遇到“event.WaitOne”时进入睡眠状态,并且不使用任何 CPU 周期,直到 proc1“设置”该事件。设置事件会导致 proc2 唤醒,现在它可以做它的事情了。因为这是一个手动重置事件,所以该事件将保持在“设置”状态,直到调用 event.Reset() 为止。

To do this, you'll need to make use of the various synchronization objects available in C#. Some examples of the available synchronization objects are System.Threading.Mutex, System.Threading.Semaphore, System.Threading.ManualResetEvent, and System.Threading.AutoResetEvent (this is not an exhaustive list, but it's the basics). The exact synchronization object you'll want depends on your specific needs.

Mutex is probably the simplest to use, so I'll give it as an example. Say I have two functions that are running in two different threads (I'll stick with your own examples, proc1 and proc2). Both functions need to access the same variable, foo. In each function that accesses foo, you'll need to "lock" your mutex first. Then do whatever you need to do, then unlock it.

For example:

class bar
{
  private int foo;
  private System.Threading.Mutex lock = new System.Threading.Mutex;

  public void proc1()
  {
    lock.WaitOne();

    // do stuff to foo

    lock.ReleaseMutex();
  }

  public void proc2()
  {
    lock.WaitOne();

    // do stuff to foo

    lock.ReleaseMutex();
  }
};

Using this method, proc1 will execute. It will try to "grab" the mutex (lock). If the mutex is already grabbed, proc1 will go to sleep until the mutex is "released" by the other thread - proc1 will sit and wait, doing nothing (and eating no CPU cycles!) until the mutex is released. Then it will lock it and do its thing. No other thread will be able to grab the mutex until proc1 is done with it.

Another option is to use an Event. C# provides two types of events - manual reset and autoreset. I'll use a manual reset event for my example.

class bar
{
  private System.Threading.ManualResetEvent event = new System.Threading.ManualResetEvent;

  public void proc1()
  {
    // do stuff

    event.Set();
  }

  public void proc2()
  {
    event.WaitOne();
    event.Reset();

    // do stuff
  }
};

In this example, when proc2 is running it goes to sleep when it hits "event.WaitOne" and uses no CPU cycles until proc1 "sets" the event. Setting the event causes proc2 to wake up, and now it can do its thing. Because this is a manual reset event, the event will stay in the "set" state until event.Reset() is called.

小姐丶请自重 2024-08-18 01:06:06

根据多线程的性质,Thread.Join 可能会起作用。它会阻塞调用线程直到线程终止,同时继续执行标准消息泵送。

Depending on the nature of the multithreading, Thread.Join may do the trick. It blocks the calling thread until the thread terminates, while continuing to perform standard message pumping.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文