.net线程同步的一些知识

简介: 同步的目的是防止多个线程访问共享数据的破坏问题,关键点: 处理同步是容易出错的 通过锁对性能会有影响 同一个时刻只允许一个线程写共享资源 一些建议 避免静态字段共享数据(只读除外) 创建的对象在线程之间不传递使用,也不需要同步 最好使用值类型,线程操作的是这些类型的拷贝,因此不需要同步...

同步的目的是防止多个线程访问共享数据的破坏问题,关键点:

处理同步是容易出错的

通过锁对性能会有影响

同一个时刻只允许一个线程写共享资源

一些建议

避免静态字段共享数据(只读除外)

创建的对象在线程之间不传递使用,也不需要同步

最好使用值类型,线程操作的是这些类型的拷贝,因此不需要同步

用户模式、内核模式基元构造

 

优点

缺点

例子

基元用户模式

使用特殊的CPU指令,速度比内核模式快

OS不能侦测到线程的阻塞,会多次反复调度

易失

Volatile construct:Thread.VolatileWrite
Thread.VolatileRead
volatile

互锁构造

Interlocked construct

System.Threading.Interlocked

[都要求传递对“包含一个简单数据类型的一个变量”的引用]

基元内核模式

Windows系统自身提供的

会阻塞线程,不会浪费CPU

用户态切换到内核态有性能损失

事件、信号量(以上两者基础上的如互斥体)

事件是内核维护的Boolean变量AutoResetEvent

信号量是由内核维护的Int32变量

互斥体和AutoResetEvent(或计数为1的Semaphore)相似

ThreadPool.RegisterWaitForSingleObject线程池等待内核对象进入可用状态,更高效的方式

混合线程同步构造:一般情况下,通过合并用户模式和内核模式同步构造,没有线程竞争时,提供了内核模式的性能;竞争时提供了内核模式的优点。

System.Threading下的混合线程同步构造

ManualResetEventSlim、SemaphoreSlim、ReaderWriterLockSlim特别处在于它们都在用户模式中“自旋”,而且都推迟到发生第一次竞争时,才创建内核模式的构造

Monitor的使用:

每个对象都使用私有的锁

///防止反复测试条件的浪费CPU的一个方法

public sealed class SynchronizedQueue<T> {

private readonly Object m_lock = new Object();

private readonly Queue<T> m_queue = new Queue<T>();

public void Enqueue(T item) {

Monitor.Enter(m_lock);

            m_queue.Enqueue(item);

Monitor.PulseAll(m_lock); // Wakeup any/all waiters 激发

Monitor.Exit(m_lock);

        }

///在有一个可供处理的数据项之前,试图出队一个数据项的线程会一直阻塞

public T Dequeue() {

Monitor.Enter(m_lock);

            // Loop waiting for condition (queue not empty)

while (m_queue.Count == 0)

Monitor.Wait(m_queue);//释放锁所有权,等待激发条件

            T item = m_queue.Dequeue();

Monitor.Exit(m_lock);

return item;

        }

    }

单例模式和Lazy中使用的锁

public Lazy(LazyThreadSafetyMode mode)

LazyInitializer.EnsureInitialized

把对象的初始化放到需要的时刻,以减少内容的占用

更详细的锁的使用和处理参考:

图书 Clr Via C#

图书资源的网站 http://transbot.blog.163.com

http://ys-f.ys168.com/?CLR_via_CSharp_3rd_Edition_Code_by_Jeffrey_Richter.zip_55bism1e0e7bkisjthit2bso0cm5bs4bs1b5bktnql0c0bu22f05f12z

相关文章
|
7月前
|
并行计算 安全 Java
C# .NET面试系列四:多线程
<h2>多线程 #### 1. 根据线程安全的相关知识,分析以下代码,当调用 test 方法时 i > 10 时是否会引起死锁? 并简要说明理由。 ```c# public void test(int i) { lock(this) { if (i > 10) { i--; test(i); } } } ``` 在给定的代码中,不会发生死锁。死锁通常是由于两个或多个线程互相等待对方释放锁而无法继续执行的情况。在这个代码中,只有一个线程持有锁,且没有其他线程参与,因此不
425 3
|
1月前
|
开发框架 Java .NET
.net core 非阻塞的异步编程 及 线程调度过程
【11月更文挑战第12天】本文介绍了.NET Core中的非阻塞异步编程,包括其基本概念、实现方式及应用示例。通过`async`和`await`关键字,程序可在等待I/O操作时保持线程不被阻塞,提高性能。文章还详细说明了异步方法的基础示例、线程调度过程、延续任务机制、同步上下文的作用以及如何使用`Task.WhenAll`和`Task.WhenAny`处理多个异步任务的并发执行。
|
6月前
|
开发框架 监控 Java
【.NET Core】多线程之线程池(ThreadPool)详解(二)
【.NET Core】多线程之线程池(ThreadPool)详解(二)
105 3
|
6月前
|
SQL 开发框架 Java
【.NET Core】多线程之线程池(ThreadPool)详解(一)
【.NET Core】多线程之线程池(ThreadPool)详解(一)
445 2
|
6月前
|
算法 安全 Java
【.NET Core】 多线程之(Thread)详解
【.NET Core】 多线程之(Thread)详解
82 1
|
数据采集 Java C++
【.NET 6】多线程的几种打开方式和代码演示
多线程无处不在,平常的开发过程中,应该算是最常用的基础技术之一了。以下通过Thread、ThreadPool、再到Task、Parallel、线程锁、线程取消等方面,一步步进行演示多线程的一些基础操作。欢迎大家围观。如果大佬们有其他关于多线程的拓展,也欢迎在评论区进行留言,大佬们的知识互助,是.net生态发展的重要一环,欢迎大佬们进行留言,帮助更多的人。
282 0
【.NET 6】多线程的几种打开方式和代码演示
|
C# Windows
.NET一个线程更新另一个线程的UI(两种实现方法及若干简化)
原文:.NET一个线程更新另一个线程的UI(两种实现方法及若干简化) 本片博文接上一篇:.NET多线程执行函数,给出实现一个线程更新另一个线程UI的两种方法。 Winform中的控件是绑定到特定的线程的(一般是主线程),这意味着从另一个线程更新主线程的控件不能直接调用该控件的成员。
1522 0
|
安全 NoSQL MongoDB
.Net线程同步技术解读
C#开发者(面试者)都会遇到lock(Monitor),Mutex,Semaphore,SemaphoreSlim这四个与锁相关的C#类型,本文期望以最简洁明了的方式阐述四种对象的区别。
.Net线程同步技术解读
|
XML 存储 开发框架
ASP.NET多线程的使用(二)
线程,是操作系统中的术语,是操作系统进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以有很多线程,每条线程并行执行不同的任务。同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。我们把用来执行用户任务的线程称为工作线程。而线程池,是一种成熟的线程使用模式。
198 0
ASP.NET多线程的使用(二)
|
存储 开发框架 Java
ASP.NET多线程的使用(一)
线程,是操作系统中的术语,是操作系统进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以有很多线程,每条线程并行执行不同的任务。同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。我们把用来执行用户任务的线程称为工作线程。而线程池,是一种成熟的线程使用模式。
331 0
ASP.NET多线程的使用(一)