You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MultiThreadingStudy/Docs/Jupyter笔记.2.5.原子操作.ipynb

275 lines
7.3 KiB
Plaintext

{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"原子操作\n",
"======="
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"在多线程环境中,因为多个线程可能会同时访问同一个资源,我们需要使用一些方式保证访问不发生冲突,其中最基础的方式就是原子操作。 \n",
"原子操作是利用 CPU 提供的特性,所以不会阻塞线程。 \n",
"线程安全方式有: \n",
"+ 使用设计,避免多线程中的资源共享\n",
"+ 利用线程本地存储,使资源复制到线程本地,实现互相独立、互不干扰\n",
"+ 使用原子操作\n",
"+ 使用锁\n",
"+ 使用信号量\n",
"+ 综合使用"
]
},
{
"cell_type": "markdown",
"metadata": {},
"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": {},
"source": [
"## .Net中的原子操作类"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
".Net中 System.Threading.Interlocked 类提供了用于执行原子操作的函数,这些函数接收引用参数(ref),也就是变量内存地址,然后针对该内存地址的值执行原子操作。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Increment\n",
"Interlocked.Increment 函数执行的原子操作属于 “获取-添加”分类执行后变量的值增加1返回的值是增加后的值即增加前的值加1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"//计数器类\n",
"public class Counter\n",
"{\n",
" //总次数\n",
" public static int TotalNumber = 0;\n",
" \n",
" //方法循环次数\n",
" public static readonly int LoopNumber = 100;\n",
"\n",
" //执行\n",
" public static void Execute()\n",
" {\n",
" for (int i = 1; i <= LoopNumber; i++)\n",
" {\n",
" //原子操作\n",
" System.Threading.Interlocked.Increment(ref TotalNumber);\n",
" }\n",
" Console.WriteLine($\"线程[{Thread.CurrentThread.ManagedThreadId.ToString(\"000\")}] 执行了累加 {LoopNumber} 次,结束时 TotalNumber = {TotalNumber}\");\n",
" }\n",
"}\n",
"\n",
"//使用域隔离和代码折叠\n",
"{\n",
" var threads = new List<Thread>()\n",
" {\n",
" new Thread(Counter.Execute){Name=\"thread_a\"},\n",
" new Thread(Counter.Execute){Name=\"thread_b\"}\n",
" };\n",
"\n",
" threads.ForEach(t => t.Start());\n",
" threads.ForEach(t => t.Join());\n",
"\n",
" //主线程信息\n",
" Console.WriteLine($\"主(执行)线程[{Thread.CurrentThread.ManagedThreadId.ToString(\"000\")}] 结束时TotalLoopNumber = {Counter.TotalNumber}\");\n",
"}\n",
"\n",
"//原子操作,多线程下多次执行结果相同"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".NET (C#)",
"language": "C#",
"name": ".net-csharp"
},
"language_info": {
"file_extension": ".cs",
"mimetype": "text/x-csharp",
"name": "C#",
"pygments_lexer": "csharp",
"version": "11.0"
},
"polyglot_notebook": {
"kernelInfo": {
"defaultKernelName": "csharp",
"items": [
{
"aliases": [],
"name": ".NET"
},
{
"aliases": [
"C#",
"c#"
],
"languageName": "C#",
"name": "csharp"
},
{
"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": [
"frontend"
],
"name": "vscode"
},
{
"aliases": [],
"name": "webview"
}
]
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}