线程相关静态变量

默认静态变量应用程序域所有线程可见。如果静态变量需要在线程间共享,同步访问也就必然了。

线程相关静态变量保证线程安全,同一时间只有一个线程可访问,且每个线程都有该静态变量的拷贝。

  1. public class MyClass
  2. {
  3. //.NET支持线程相关静态变量
  4. //该特性只可修饰类的静态成员变量,不能用于属性,方法
  5. [ThreadStatic]
  6. private static m_MyString;
  7. public static string MyString
  8. {
  9. set { m_MyString = value; }
  10. get { return m_MyString; }
  11. }
  12. }
public class MyClass
{
//.NET支持线程相关静态变量
//该特性只可修饰类的静态成员变量,不能用于属性,方法
[ThreadStatic]
private static m_MyString;
public static string MyString
{
set { m_MyString = value; }
get { return m_MyString; }
}
}

线程本地存储(TLS)

全局托管堆上分配的对象对于所有应用程序域的所有线程都可见可访问(因此需要同步访问机制)。

.NET提供了线程专用堆TLS,无需同步那些分配到TLS上的对象访问,因为只有一个线程可以访问他们。

TLS提供了槽(LocalDataStoreSlot对象),用来存储对象。分为:命名槽(一定要显示释放),未命名槽(垃圾回收器自动释放)。

命名槽:

  1. Thread.CurrentThread.Name = "66";
  2. int number = 8;
  3. //显示释放命名槽
  4. Thread.FreeNamedDataSlot("My_TLS_Slot");
  5. //在当前线程上分配一命名槽
  6. LocalDataStoreSlot dataSlot = Thread.AllocateNamedDataSlot("My_TLS_Slot");
  7. //在当前线程上将数据存入命名槽(只有当前线程中的成员才可以访问)
  8. Thread.SetData(dataSlot, 8);
  9. //新建另一线程
  10. Thread thread = new Thread(GetData_2);
  11. thread.Name = "lulu";
  12. thread.Start();
  13. GetData();
  14. private void GetData()
  15. {
  16. object obj;
  17. //获取当前线程命名槽
  18. LocalDataStoreSlot dataSlot = Thread.GetNamedDataSlot("My_TLS_Slot");
  19. //获取当前线程槽中存储的值
  20. obj = Thread.GetData(dataSlot);
  21. int number = (int)obj;
  22. //输出:66 , 8
  23. //说明槽中数据只由创建槽的线程访问(只有一个线程可访问)
  24. Response.Write(Thread.CurrentThread.Name + " , " + number);
  25. }
  26. private void GetData_2()
  27. {
  28. object obj;
  29. LocalDataStoreSlot dataSlot = Thread.GetNamedDataSlot("My_TLS_Slot");
  30. obj = Thread.GetData(dataSlot);
  31. //输出:lulu
  32. //说明访问不到槽中数据,因为当前方法由另一线程调用
  33. if (obj == null)
  34. {
  35. Response.Write(Thread.CurrentThread.Name);
  36. }
  37. }
Thread.CurrentThread.Name = "66";

int number = 8;
//显示释放命名槽
Thread.FreeNamedDataSlot("My_TLS_Slot");
//在当前线程上分配一命名槽
LocalDataStoreSlot dataSlot = Thread.AllocateNamedDataSlot("My_TLS_Slot");
//在当前线程上将数据存入命名槽(只有当前线程中的成员才可以访问)
Thread.SetData(dataSlot, 8); //新建另一线程
Thread thread = new Thread(GetData_2);
thread.Name = "lulu";
thread.Start(); GetData(); private void GetData()
{
object obj;
//获取当前线程命名槽
LocalDataStoreSlot dataSlot = Thread.GetNamedDataSlot("My_TLS_Slot");
//获取当前线程槽中存储的值
obj = Thread.GetData(dataSlot); int number = (int)obj; //输出:66 , 8
//说明槽中数据只由创建槽的线程访问(只有一个线程可访问)
Response.Write(Thread.CurrentThread.Name + " , " + number);
} private void GetData_2()
{
object obj;
LocalDataStoreSlot dataSlot = Thread.GetNamedDataSlot("My_TLS_Slot");
obj = Thread.GetData(dataSlot); //输出:lulu
//说明访问不到槽中数据,因为当前方法由另一线程调用
if (obj == null)
{
Response.Write(Thread.CurrentThread.Name);
}
}

未命名槽:

  1. //共享该对象
  2. private LocalDataStoreSlot dataSlot;
  3. protected void Page_Load(object sender, EventArgs e)
  4. {
  5. Thread.CurrentThread.Name = "66";
  6. //在当前线程上分配一未命名槽(由垃圾回收器释放,无需显示释放)
  7. dataSlot = Thread.AllocateDataSlot();
  8. //在当前线程上将数据存入未命名槽(只有当前线程中的成员才可以访问)
  9. Thread.SetData(dataSlot, 8);
  10. //创建一新线程
  11. Thread thread = new Thread(GetData_2);
  12. thread.Name = "lulu";
  13. thread.Start();
  14. GetData();
  15. }
  16. private void GetData()
  17. {
  18. //获取当前线程未命名槽中值
  19. object obj = Thread.GetData(dataSlot);
  20. Response.Write(Thread.CurrentThread.Name + " , " + (int)obj);
  21. }
  22. private void GetData_2()
  23. {
  24. object obj = Thread.GetData(dataSlot);
  25. if (obj == null)
  26. {
  27. Response.Write(Thread.CurrentThread.Name);
  28. }
  29. }
//共享该对象
private LocalDataStoreSlot dataSlot; protected void Page_Load(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "66"; //在当前线程上分配一未命名槽(由垃圾回收器释放,无需显示释放)
dataSlot = Thread.AllocateDataSlot();
//在当前线程上将数据存入未命名槽(只有当前线程中的成员才可以访问)
Thread.SetData(dataSlot, 8); //创建一新线程
Thread thread = new Thread(GetData_2);
thread.Name = "lulu";
thread.Start(); GetData();
} private void GetData()
{
//获取当前线程未命名槽中值
object obj = Thread.GetData(dataSlot);
Response.Write(Thread.CurrentThread.Name + " , " + (int)obj);
} private void GetData_2()
{
object obj = Thread.GetData(dataSlot);
if (obj == null)
{
Response.Write(Thread.CurrentThread.Name);
}
}

线程池

由.NET管理,包含一组线程随时准备为应用程序的请求服务(异步调用,远程调用,计时器调用都用到线程池)。可通过ThreadPool静态类访问。

线程池中实际有2种线程:工作线程,完成端口线程。

默认情况下,线程池工作线程最大数是每个CPU每个进程25个。

多线程和并发管理 .NET多线程服务的更多相关文章

  1. Java多线程与并发基础

    CS-LogN思维导图:记录专业基础 面试题 开源地址:https://github.com/FISHers6/CS-LogN 多线程与并发基础 实现多线程 面试题1:有几种实现线程的方法,分别是什么 ...

  2. Java 并发性和多线程

    一.介绍 在过去单 CPU 时代,单任务在一个时间点只能执行单一程序.之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程.虽然并不是真正意义上的“同一时间点”,而是多个任务或进程共享一个 ...

  3. python 并发编程之多线程

    一.线程理论 1.什么是线程 ​ 多线程(即多个控制线程)的概念是,在一个进程中存在多个线程,多个线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源. 所以,进程只是用来把资 ...

  4. 30 python 并发编程之多线程

    一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍 官网链接:https://docs.python ...

  5. 百万年薪python之路 -- 并发编程之 多线程 二

    1. 死锁现象与递归锁 进程也有死锁与递归锁,进程的死锁和递归锁与线程的死锁递归锁同理. 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因为争夺资源而造成的一种互相等待的现象,在无外力的作用 ...

  6. Java 多线程与并发【原理第二部分笔记】

    Java 多线程与并发[原理第二部分笔记] 什么是Java内存模型中的happens-before Java内存模型,即JMM,本身是一种抽象的概念,并不是真实存在的,他描述的是一组规则或者说是一种规 ...

  7. JAVA 多线程和并发学习笔记(三)

    Java并发编程中使用Executors类创建和管理线程的用法 1.类 Executors Executors类可以看做一个“工具类”.援引JDK1.6 API中的介绍: 此包中所定义的 Execut ...

  8. java 并发性和多线程 -- 读感 (一 线程的基本概念部分)

    1.目录略览      线程的基本概念:介绍线程的优点,代价,并发编程的模型.如何创建运行java 线程.      线程间通讯的机制:竞态条件与临界区,线程安全和共享资源与不可变性.java内存模型 ...

  9. JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

随机推荐

  1. EasyUI DataGrid 窗口大小自适用--------------未测试

    EasyUI 新版本里添加了 fit 属性,不需要老版本的那么复杂,重新load DataGrid.但是昨天用的时间发现只有一个DataGrid的时候用fit:true 很好使,但是如果有其它元素,如 ...

  2. DataTrigger的几个用法

    1.用在textbox等输入控件上,验证输入是否合法. <Window.Resources> <Style TargetType="TextBox"> &l ...

  3. C#读取文件为byte数组

    private byte[] FileContent(string fileName) { using (FileStream fs = new FileStream(fileName, FileMo ...

  4. Umbraco部署到IIS中权限问题(back office没有权限新建template)

    在开发项目中,发现把基于Umbraco平台开发的网站部署到服务器的IIS之后,访问该网站的back office 在back office中增加一个template时,发送错误,提示 Access t ...

  5. Codeforces 711 D. Directed Roads (DFS判环)

    题目链接:http://codeforces.com/problemset/problem/711/D 给你一个n个节点n条边的有向图,可以把一条边反向,现在问有多少种方式可以使这个图没有环. 每个连 ...

  6. LA4329 Ping pong(树状数组与组合原理)

    N (3N20000)ping pong players live along a west-east street(consider the street as a line segment). E ...

  7. CString转换成int CString类相应函数

    CString 型转化成 int 型 把 CString 类型的数据转化成整数类型最简单的方法就是使用标准的字符串到整数转换例程. 虽然通常你怀疑使用_atoi()函数是一个好的选择,它也很少会是一个 ...

  8. 我的Memcache学习笔记

    一.编绎安装Memcached 二.Memcached基本命令 四.PHP扩展模块安装 五.设置session用memcache来存储 六.PHP使用Memcache的一致性哈希连接方式 七.Memc ...

  9. VC中常用的宏[转]

    我们在VS环境中开发的时候,会遇到很多宏定义,这些宏可以应用到代码中,或用于编译.工程选项等设置,总之是我们开发中必不可少的工具,有必要做一个总结.有些宏是C/C++定义的,有些宏是VC环境预定义的. ...

  10. 转载:rebar和erlang

    使用rebar生成erlang release 并进行热代码升级 http://blog.sina.com.cn/s/blog_6530ad590100wmkn.html 使用rebar工具开发erl ...