c# - 为什么多线程程序需要锁定令牌
问题描述
下面是一个例子
public class Printer
{
// Lock token.
private object threadLock = new object();
public void PrintNumbers()
{
// Use the lock token.
lock (threadLock)
{
...
}
}
}
但是我仍然没有得到线程令牌的概念,为什么有必要?线程令牌与C中的信号量相同吗?但是对于 C 程序,信号量只是一个整数?
解决方案
lock
是一个互斥体,像 POSIXpthread_mutex_lock
和pthread_mutex_unlock
C一样工作。
一次只允许一段代码获取给定对象上的锁,因此这是一种同步线程的方式(不一定是最好的方式,但这是一个更详细和高度上下文相关的答案)。
例如,以下代码同时运行几个线程:
- 将数字数组的每个元素递增 10,
- 另一个打印数组的内容
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);
}
})
);
由于它们同时运行,因此输出类似于:
11 2 13 4 5 6 7 18 9 10
有些数字会增加,有些则不会,而且每次都不同。
但是,将循环包裹在锁中的相同代码:
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);
}
}
})
);
这只会输出两件事之一,具体取决于哪个循环首先获取锁:
11 12 13 14 15 16 17 18 19 20
或者
1 2 3 4 5 6 7 8 9 10
这两个任务之间没有实际的协调,所以你得到哪个集合(增加或不增加)只取决于哪个首先获得锁。
推荐阅读
- sql - SQL - 仅显示日期最新的行
- python - 是否可以在 python 中“流式传输”一个变量?
- python - 如何分析芹菜任务的内存使用情况?
- javascript - 将相关元素嵌套在一起父/子
- highcharts - 是否可以根据实时交易在图表上更新或绘制最后一根蜡烛?
- java - 有没有办法在 Maven 中为 javacv 的本机部分设置依赖项,而无需手动安装和设置 java.library.path?
- python - Django 3、Python 3.8 找不到我的模板
- pandas - Pandas:在日期时间索引和另一列上执行 merge_asof 时出现关键错误
- python - 查看从函数中调用的所有函数的代码
- machine-learning - PyTorch ConvNet 随机学习单个标签并卡住