using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace MultiThreadingStudy.Core
{
///
/// 线程本地存储 执行器
///
public class ThreadLocalStorage
{
///
/// 不使用线程本地存储
///
public static void Run()
{
var demo = new Computer();
var thread_a = new Thread(new ThreadStart(demo.SumCount)) { Name = "thread_a" };
var thread_b = new Thread(new ThreadStart(demo.SumCount)) { Name = "thread_b" };
thread_a.Start();
thread_b.Start();
thread_a.Join();
thread_b.Join();
//调用线程:[主线程|内核线程] 共享字段的值。不加处理的话,可能小于多线程调用次数之和。
Console.WriteLine("调用线程的共享变量值 = " + Computer.TotalCount);
}
///
/// 使用 ThreadStatic 特性
///
public static void UseThreadStaticAttribute()
{
var demo = new ThreadStaticComputer();
var thread_a = new Thread(new ThreadStart(demo.SumCount)) { Name = "thread_a" };
var thread_b = new Thread(new ThreadStart(demo.SumCount)) { Name = "thread_b" };
thread_a.Start();
thread_b.Start();
thread_a.Join();
thread_b.Join();
//调用线程:[主线程|内核线程] 共享字段的值。不加处理的话,可能小于多线程调用次数之和。
Console.WriteLine("调用线程的共享变量值 = " + Computer.TotalCount);
}
///
/// 使用数据槽
///
public static void UseDataSlot()
{
var demo = new DataSlotComputer();
var thread_a = new Thread(new ThreadStart(demo.SumCount)) { Name = "thread_a" };
var thread_b = new Thread(new ThreadStart(demo.SumCount)) { Name = "thread_b" };
thread_a.Start();
thread_b.Start();
thread_a.Join();
thread_b.Join();
//调用线程:[主线程|内核线程] 共享字段的值。不加处理的话,可能小于多线程调用次数之和。
Console.WriteLine("调用线程的共享变量值 = " + Computer.TotalCount);
}
///
/// 使用 ThreadLocal 泛型类
///
public static void UseThreadLocalClass()
{
var demo = new ThreadLocalComputer();
var thread_a = new Thread(new ThreadStart(demo.SumCount)) { Name = "thread_a" };
var thread_b = new Thread(new ThreadStart(demo.SumCount)) { Name = "thread_b" };
thread_a.Start();
thread_b.Start();
thread_a.Join();
thread_b.Join();
//调用线程:[主线程|内核线程] 共享字段的值。不加处理的话,可能小于多线程调用次数之和。
Console.WriteLine("调用线程的共享变量值 = " + Computer.TotalCount);
}
}
///
/// 不使用本地存储
///
///
/// 由于 ++ -- += -= 等对共享变量的操作不是原子性的,多线程下是不安全的。
///
public class Computer
{
///
/// 总计算次数
///
//[ThreadStatic]
public static int TotalCount = 0;
///
/// 循环次数
///
public readonly int LoopNumber = 1000;
///
/// 累加计数
///
public void SumCount()
{
for (int i = 1; i <= LoopNumber; i++)
{
//因为 += 是和等于的两步操作,所以不是线程安全的。
TotalCount += 1;
//如果使用原子操作,则是线程安全的
//Interlocked.Increment(ref TotalCount);
//加休眠是为了让并发效果明显,不加休眠可以增加循环次数
Thread.Sleep(1);
}
Console.WriteLine($"线程[{Thread.CurrentThread.ManagedThreadId.ToString("000")}]执行后,共享变量 {nameof(TotalCount)} = {TotalCount}");
}
}
///
/// 使用本地存储:ThreadStatic 特性
///
///
/// 特点:只能用于静态变量上,不能用于实例上(语法不报错,实际不起作用)
///
public class ThreadStaticComputer
{
///
/// 总计算次数
///
[ThreadStatic]
public static int TotalCount = 0;
///
/// 循环次数
///
public readonly int LoopNumber = 100;
///
/// 累加计数
///
public void SumCount()
{
for (int i = 1; i <= LoopNumber; i++)
{
TotalCount += 1;
Thread.Sleep(0);
}
Console.WriteLine($"线程[{Thread.CurrentThread.ManagedThreadId.ToString("000")}]执行后,共享变量 {nameof(TotalCount)} = {TotalCount}");
}
}
///
/// 使用本地存储:数据槽
///
///
/// 特点:可以用于静态也可用于实例
///
public class DataSlotComputer
{
///
/// 总计算次数
///
public static int TotalCount = 0;
///
/// 循环次数
///
public readonly int LoopNumber = 100;
///
/// 数据槽
///
public LocalDataStoreSlot storeSlot = Thread.AllocateDataSlot();
///
/// 累加计数值
///
public void SumCount()
{
for (int i = 1; i <= LoopNumber; i++)
{
Thread.SetData(storeSlot, i);
//加休眠是为了让并发效果明显,不加休眠可以增加循环次数
Thread.Sleep(0);
}
//严格讲,这里也不是线程安全的。少量线程不安全的概率很小.可以使用原子操作实现。
TotalCount += (int)Thread.GetData(storeSlot);
//保证线程安全的话,可用原子操作
//Interlocked.Add(ref TotalCount, (int)Thread.GetData(storeSlot));
Console.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId.ToString("000")}执行后,共享变量{nameof(TotalCount)} = {TotalCount}");
}
}
///
/// 使用本地存储:ThreadLocal泛型类
///
///
/// 特点:1、对静态和实例字段都提供了线程本地存储支持,并允许指定默认值
/// 2、ThreadLocal的值是延迟计算的:每线程第一次调用时计算实际的值
///
public class ThreadLocalComputer
{
///
/// 总计算次数
///
public static int TotalCount = 0;
///
/// 循环次数
///
public readonly int LoopNumber = 100;
///
/// 线程本地存储数据
///
public static ThreadLocal threadTotalCount = new ThreadLocal();
///
/// 累加计数值
///
public void SumCount()
{
for (int i = 1; i <= LoopNumber; i++)
{
threadTotalCount.Value += 1;
//加休眠是为了让并发效果明显,不加休眠可以增加循环次数
Thread.Sleep(0);
}
TotalCount += threadTotalCount.Value;
//保证线程安全的话,可用原子操作
//Interlocked.Add(ref TotalCount, threadTotalCount.Value);
Console.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId.ToString("000")}执行后,共享变量{nameof(TotalCount)} = {TotalCount}");
}
}
}