docs: 文档更新

master
bicijinlian 2 years ago
parent 33842cd385
commit 8d510e020c

@ -1008,6 +1008,60 @@
],
"languageName": null,
"name": "vscode"
},
{
"aliases": [],
"name": ".NET"
},
{
"aliases": [
"f#",
"F#"
],
"languageName": "F#",
"name": "fsharp"
},
{
"aliases": [],
"languageName": "HTML",
"name": "html"
},
{
"aliases": [
"js"
],
"languageName": "JavaScript",
"name": "javascript"
},
{
"aliases": [],
"languageName": "KQL",
"name": "kql"
},
{
"aliases": [],
"languageName": "Mermaid",
"name": "mermaid"
},
{
"aliases": [
"powershell"
],
"languageName": "PowerShell",
"name": "pwsh"
},
{
"aliases": [],
"languageName": "SQL",
"name": "sql"
},
{
"aliases": [],
"name": "value"
},
{
"aliases": [],
"name": "webview"
}
]
}

@ -28,8 +28,11 @@
}
},
"source": [
"学习 Thread执行各种 Thread 操作。 \n",
"特别注意NoteBook 本身的运行线程是后台线程,不会等待由其创建的线程执行结束。与控制台等应用有区别。 "
".Net中托管线程分为抢占模式和合作模式区分这两种模式主要是为了GC的实现。 \n",
"\n",
"处于合作模式的线程可以自由地访问托管堆上的对象处理抢占模式的线程则不能访问托管堆上的对象如果需要访问则必须等待GC结束并切换到合作模式。因为托管代码随时需要访问托管堆所以托管代码必须在合作模式下运行而非托管代码则没有这个限制。进入抢占模式后托管代码暂停执行而非托管代码可以继续做与.Net对象无关的处理。 \n",
"\n",
"模式切换分为主动切换和被动切换"
]
},
{
@ -44,33 +47,7 @@
}
},
"source": [
"## 全局设置语言设置、Nuget包引用、空间引用等"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"//全局设置\n",
"#!csharp\n",
"using System.Threading;\n",
"using System.Threading.Channels;\n",
"using System.Threading.Tasks;\n",
"\n",
"//全局变量\n",
"var noteBookThreadDesc = \"NoteBook线程\";"
"GC安全点"
]
}
],

@ -0,0 +1,289 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"source": [
"线程本地存储\n",
"============================== "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"source": [
"线程本地存储(Thread Local Storge,简称TLS)机制用于实现按线程隔离的线程本地变量,对于同一个线程本地变量,各个线程分别有独立的值,修改的值只能修改的线程可见。 <br/>\n",
"\n",
"线程要地存储可以分为原生实现与托管实现,原生实现指的是调用操作系统提供的接口访问原生线程对应的线程本地存储,而托管实现指的是调用.net提供的接口访问托管线程对应的线程本地存储。 <br/>\n",
"\n",
"原生实现在Windows和linux上的实现不同但同样都是调用系统提供的接口。 <br/>"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"source": [
"## 全局设置语言设置、Nuget包引用、空间引用等"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"//全局设置\n",
"#!csharp\n",
"using System.Threading;\n",
"using System.Threading.Channels;\n",
"using System.Threading.Tasks;\n",
"\n",
"//全局变量\n",
"var noteBookThreadDesc = \"NoteBook线程\";\n",
"\n",
"//全局方法\n",
"//显示线程信息\n",
"public void ShowThreadInfo(Thread showThread=null, string describe = null)\n",
"{\n",
" if(showThread == null)\n",
" {\n",
" showThread = Thread.CurrentThread;\n",
" }\n",
"\n",
" if(string.IsNullOrWhiteSpace(describe))\n",
" {\n",
" describe = showThread.Name == null ? \"无名\" : showThread.Name;\n",
" }\n",
"\n",
" Console.WriteLine($\"{describe}线程ID{showThread.ManagedThreadId} \");\n",
" Console.WriteLine($\"{describe}线程名:{showThread.Name} \");\n",
" Console.WriteLine($\"{describe}线程状态:{showThread.ThreadState} \");\n",
" Console.WriteLine($\"{describe}线程模式:{showThread.GetApartmentState()} \");\n",
" Console.WriteLine($\"{describe}激活:{(showThread.IsAlive ? \"活动\" : \"非活动\")} \");\n",
" Console.WriteLine($\"{describe}线程池线程:{(showThread.IsThreadPoolThread ? \"是的\" : \"否\")} \");\n",
" Console.WriteLine($\"{describe}后台线:{(showThread.IsBackground ? \"是的\" : \"不是\")} \");\n",
" Console.WriteLine($\"{describe}区域:{showThread.CurrentCulture}\");\n",
" Console.WriteLine($\"{describe}UI区域{showThread.CurrentUICulture}\");\n",
" Console.WriteLine($\"{describe}优先级:{showThread.Priority}\");\n",
"}\n",
"\n",
"//显示线程状态\n",
"public void ShowThreadState(Thread showThread=null, string describe = null)\n",
"{\n",
" if(showThread == null)\n",
" {\n",
" showThread = Thread.CurrentThread;\n",
" }\n",
"\n",
" if(string.IsNullOrWhiteSpace(describe))\n",
" {\n",
" describe = showThread.Name == null ? \"无名\" : showThread.Name;\n",
" }\n",
" Console.WriteLine($\"{describe}线程状态:{showThread.ThreadState} \");\n",
"}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"source": [
"## ThreadStatic Attribute 属性的实现"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"source": [
"在 .NET 中标记了[ThreadStatic]特性的全局变量就是托管线程本地变量。 <br/>\n",
"\n",
"在 .NET 中每个托管对象都关联一个TLB(Thread Local Block)表TLB表以 AppDomain ID 为索引保存 TLM(Thread Local Module)表TLM表以模块ID为索引保存托管线程本地存储空间的开始地址。当 .NET 运行时加载一个程序集时,会枚举程序集中的模块与模块中的全局变量,然后按是否线程本地变量分成两部分,非线程本地变量会保存在 AppDomain 对应的高频堆中;而线程本地变量只计算偏移值,存储空间会在首次访问时分配。 "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"{ //隔离代码\n",
"\n",
" Console.WriteLine(\"花括号隔离代码,避免上下段互相影响!\");\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"public class Demo\n",
"{\n",
"\n",
" \n",
"}\n",
"{\n",
"\n",
"\n",
"}"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".NET (C#)",
"language": "C#",
"name": ".net-csharp"
},
"polyglot_notebook": {
"kernelInfo": {
"defaultKernelName": "csharp",
"items": [
{
"aliases": [
"c#",
"C#"
],
"languageName": "C#",
"name": "csharp"
},
{
"aliases": [
"frontend"
],
"languageName": null,
"name": "vscode"
},
{
"aliases": [],
"languageName": null,
"name": ".NET"
},
{
"aliases": [
"f#",
"F#"
],
"languageName": "F#",
"name": "fsharp"
},
{
"aliases": [],
"languageName": "HTML",
"name": "html"
},
{
"aliases": [
"js"
],
"languageName": "JavaScript",
"name": "javascript"
},
{
"aliases": [],
"languageName": "KQL",
"name": "kql"
},
{
"aliases": [],
"languageName": "Mermaid",
"name": "mermaid"
},
{
"aliases": [
"powershell"
],
"languageName": "PowerShell",
"name": "pwsh"
},
{
"aliases": [],
"languageName": "SQL",
"name": "sql"
},
{
"aliases": [],
"languageName": null,
"name": "value"
},
{
"aliases": [],
"name": "webview"
}
]
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

@ -1,21 +1,21 @@
# **并行与并发**
# 概念
## 概念
**并发**:同时发生(申请):申请者(应用)将多个任务`同时或同一时间间隔`向`单一执行者(`CPU)申请执行;执行者同时接收或同时存在多外执行任务,`交替(非同时)执行`,因执行的非常快,`在申请方看来,是多个申请同时得到执行`。
**并行**:同时执行:申请者(应用)将多个任务`同一时刻`向`多个执行者(`CPU)申请执行;多个执行者`同时接收并同时执行`。
## 区别
## 区别
+ 对象不同:并发针对单一执行者(CPU),并行针对多个执行者(CPU)
+ **对象不同**:并发针对单一执行者(CPU),并行针对多个执行者(CPU)
+ 时间不同并发指同一时间间隔申请者宏观上看任务是同时得到处理因为执者执行的非常快交替执行的时间片很小执行者微观上是交替执行一个执行者同一时刻只能执行一个任务并行指同一时刻多个执行者CPU同时处理多个任务其中每个处理者处理一个任务
+ **时间不同**并发指同一时间间隔申请者宏观上看任务是同时得到处理因为执者执行的非常快交替执行的时间片很小执行者微观上是交替执行一个执行者同一时刻只能执行一个任务并行指同一时刻多个执行者CPU同时处理多个任务其中每个处理者处理一个任务
+ 含义不同:并发同一执行者,宏观上同时处理多个任务;并行是多个执行者,微观上同一时刻,执行多个任务。
+ **含义不同**:并发同一执行者,宏观上同时处理多个任务;并行是多个执行者,微观上同一时刻,执行多个任务。
## 联系
## 联系
+ 单核 CPU只能并发不能并行提高响应能力。
+ **单核 CPU**:只能并发不能并行;提高响应能力。
+ 多核 CPU多核上可以并行提高吞吐量同时在每个核心上可能并发提高响应能力。
+ **多核 CPU**:多核上可以并行,提高吞吐量;同时在每个核心上可能并发,提高响应能力。

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MultiThreadingStudy.xUnitTest
{
/// <summary>
/// 进程测试
/// </summary>
public class ProsessTest
{
private ITestOutputHelper _output;
public ProsessTest(ITestOutputHelper testOutput)
{
_output = testOutput;
}
[Fact]
public void Test()
{
ShowProcessInfo();
}
private void ShowProcessInfo(Process? process = null)
{
if (process == null) { process = Process.GetCurrentProcess(); }
_output.WriteLine($"进程名:{ process.ProcessName }");
_output.WriteLine($"进程Id{ process.Id }");
_output.WriteLine($"进程SessionId{ process.SessionId }");
_output.WriteLine($"机器名:{ process.MachineName }");
_output.WriteLine($"基本优先级:{ process.BasePriority }");
_output.WriteLine($"是否RaisingEvents{ process.EnableRaisingEvents }");
_output.WriteLine($"进程状态:{ (process.HasExited ? "退":"")}");
if (process.HasExited)
{
_output.WriteLine($"退出码:{process.ExitCode}");
_output.WriteLine($"退出时间:{process.ExitTime}");
}
_output.WriteLine($"句柄数:{ process.HandleCount }");
_output.WriteLine($"页内存大小:{ process.PagedMemorySize64 }");
_output.WriteLine($"页系统内存大小:{ process.PagedSystemMemorySize64 }");
_output.WriteLine($"峰值虚拟内存:{ process.PeakVirtualMemorySize64 }");
_output.WriteLine($"峰值工作内存:{ process.PeakWorkingSet64 }");
_output.WriteLine($"进程名:{ process.PriorityBoostEnabled }");
_output.WriteLine($"专用内存大小:{ process.PrivateMemorySize64 }");
//_output.WriteLine($"开始信息:{ process.StartInfo }");
_output.WriteLine($"开始时间:{ process.StartTime }");
_output.WriteLine($"线程数量:{ process.Threads.Count }");
_output.WriteLine($"总进程时间量:{ process.TotalProcessorTime }");
_output.WriteLine($"用户进程时间量:{ process.UserProcessorTime }");
}
}
}

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MultiThreadingStudy.xUnitTest
{
/// <summary>
/// 线程的本地存储
/// </summary>
public class ThreadLocalStorageTest
{
public ThreadLocalStorageTest()
{
}
}
}

@ -1,5 +1,10 @@
global using Xunit;
global using Xunit.Abstractions;
global using Xunit.Extensions;
global using Xunit.Sdk;
global using System.Threading;
global using System.Threading.Channels;
global using System.Threading.Tasks;
global using System.Threading.Tasks;
global using System.Diagnostics;
Loading…
Cancel
Save