简体   繁体   English

为什么多线程程序需要锁定令牌

[英]why lock tokens are needed for multithreading programs

Below is an example 下面是一个例子

public class Printer
{
    // Lock token.
    private object threadLock = new object();
    public void PrintNumbers()
    {
       // Use the lock token.
       lock (threadLock)
       {
           ...
       }
    }
}

but I still don't get the concept of a thread token, why is it necessary? 但是我仍然不知道线程令牌的概念,为什么有必要? is a thread token same thing as Semaphore in C? 线程令牌与C中的信号量是一样的吗? But for C programs, a Semaphore is just a integer? 但是对于C程序,信号量只是整数吗?

lock is a mutex, and works like POSIX pthread_mutex_lock and pthread_mutex_unlock in C. lock是一个互斥锁,其作用类似于C语言中的POSIX pthread_mutex_lockpthread_mutex_unlock

Only one piece of code is allowed to acquire a lock on a given object at once, so it's a way of synchronizing threads (not necessarily the best way, but that's a much more detailed and highly contextual answer). 一次只允许一段代码获取给定对象的锁,因此这是一种同步线程的方式(不一定是最佳方式,但这是一种更为详尽且高度上下文相关的答案)。


As an example, the following code runs a couple threads at the same time: 例如,以下代码可同时运行多个线程:

  • one increments each element of an array of numbers by 10, 一个将数字数组的每个元素加10,
  • the other prints the contents of the array 另一个打印数组的内容
var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

Task.WhenAll(
  Task.Run(() =>
  {
    for (var i = 0; i < 10; i++)
    {
      numbers[i] += 10;
      Thread.Sleep(10);
    }
  }),
  Task.Run(() =>
  {
    foreach (var i in numbers)
    {
      Console.Write(i + " ");
      Thread.Sleep(10);
    }
  })
);

Since they run at the same time, the output is something like: 由于它们同时运行,因此输出类似于:

11 2 13 4 5 6 7 18 9 10 11 2 13 4 5 6 7 18 9 10

Some numbers are incremented, others are not, and it's different every time. 有些数字是递增的,有些数字不是,并且每次都不同。

The same code with the loops wrapped in a lock, however: 但是,循环包含在锁中的相同代码:

object threadLock = new object();
var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

Task.WhenAll(
  Task.Run(() =>
  {
    lock (threadLock)
    {
      for (var i = 0; i < 10; i++)
      {
        numbers[i] += 10;
        Thread.Sleep(10);
      }
    }
  }),
  Task.Run(() =>
  {
    lock (threadLock)
    {
      foreach (var i in numbers)
      {
        Console.Write(i + " ");
        Thread.Sleep(10);
      }
    }
  })
);

This only ever outputs one of the two things, depending on which loop acquires the lock first: 这仅输出两件事之一,具体取决于哪个循环首先获取锁:

11 12 13 14 15 16 17 18 19 20 11 12 13 14 15 16 17 18 19 20

or 要么

1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10

There's no actual coordination between the two tasks, so which set you get (incremented or not) just depends on which happens to acquire the lock first. 这两个任务之间没有实际的协调,因此您获得(递增或不递增)哪个设置仅取决于哪个首先获得了锁定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM