C#多线程技术总结(同步)

二、串行(同步):

1.lock、Monitor--注意锁定的对象必需是引用类型(string类型除外)

示例:

        private static object syncObject = new object();

        private static void TaskWork(object i)
        {
            Console.WriteLine("我是任务:{0}",i);
            lock (syncObject)
            {
                Thread.Sleep(1000);
                Console.WriteLine("我是任务:{0},线程ID:{1}",i,Thread.CurrentThread.ManagedThreadId);
            }

            try
            {
                Monitor.Enter(syncObject);
                Console.WriteLine("我是任务:{0},线程ID:{1}", i, Thread.CurrentThread.ManagedThreadId);
            }
            finally
            {
                Monitor.Exit(syncObject);
            }
        }

//调用
Task.Factory.StartNew(TaskWork,1);
Task.Factory.StartNew(TaskWork, 2);

2.Interlocked

示例:

            int i=1;
            Interlocked.Increment(ref i); //增量+1=2;
            Console.WriteLine("i当前的值:{0}", i);

            Interlocked.Decrement(ref i); //减量-1=0;
            Console.WriteLine("i当前的值:{0}", i);

            Interlocked.Exchange(ref i, 2);//赋值=2;
            Console.WriteLine("i当前的值:{0}",i);

            Interlocked.CompareExchange(ref i, 10, 2);//比较交换值,当i=2时,则将i赋值为10;
            Console.WriteLine("i当前的值:{0}", i);

3.Mutex--可以实现进程间的同步,甚至是两个远程进程间的同步

示例:

            var t1 = new Task(() =>
            {
                Console.WriteLine("我是第一个任务!");
                Mutex m = new Mutex(false, "test");
                m.WaitOne();
                Console.WriteLine("第一个任务完成!");
                m.ReleaseMutex();
            });

            var t2 = new Task(() =>
            {
                Console.WriteLine("我是第二个任务!");
                Mutex m = new Mutex(false, "test");
                m.WaitOne();
                Console.WriteLine("第二个任务完成!");
                m.ReleaseMutex();
            });

            t1.Start();
            t2.Start();

4.ReaderWriterLock 、ReaderWriterLockSlim--如果在某一时刻资源并没有获取写的独占权,那么可以获得多个读的访问权,单个写入的独占权,如果某一时刻已经获取了写入的独占权,那么其它读取的访问权必须进行等待.

示例:

        static ReaderWriterLock rwLock = new ReaderWriterLock();

        static void Read(object state)
        {
            Console.WriteLine("我是读线程,线程ID是:{0}",Thread.CurrentThread.ManagedThreadId);
            rwLock.AcquireReaderLock(Timeout.Infinite);//无限期等待,需要显式调用ReleaseReaderLock释放锁
            var readList = state as IEnumerable<int>;
            foreach (int item in readList)
            {
                Console.WriteLine("读取当前的值为:{0}", item);
                Thread.Sleep(500);
            }
            Console.WriteLine("读完成,线程ID是:{0}", Thread.CurrentThread.ManagedThreadId);
            rwLock.ReleaseReaderLock();

        }

        static void Write(object state)
        {
            Console.WriteLine("我是写线程,线程ID是:{0}", Thread.CurrentThread.ManagedThreadId);
            rwLock.AcquireWriterLock(Timeout.Infinite); //无限期等待,需要显式调用ReleaseWriterLock释放锁
            var writeList = state as List<int>;
            int lastCount=writeList.Count();
            for (int i = lastCount; i <= 10+lastCount; i++)
            {
                writeList.Add(i);
                Console.WriteLine("写入当前值:{0}",i);
                Thread.Sleep(500);
            }
            Console.WriteLine("写完成,线程ID是:{0}", Thread.CurrentThread.ManagedThreadId);
            rwLock.ReleaseWriterLock();
        }

    //调用:
            var rwList = new List<int>();

            var t1 = new Thread(Write);
            var t2 = new Thread(Read);
            var t3 = new Thread(Write);
            var t4 = new Thread(Read);

            t1.Start(rwList);
            t2.Start(rwList);
            t3.Start(rwList);
            t4.Start(rwList);

5.SynchronizationAttribute--确保某个类的实例在同一时刻只能被一个线程访问,类的定义要求:A.类上必需标记SynchronizationAttribute特性,B.类必需继承自System.ContextBoundObject对象

示例:

    [Synchronization(SynchronizationAttribute.REQUIRED,true)]
    public class Account : System.ContextBoundObject
    {
        private static int _balance;
        public int Blance
        {
            get
            {
                return _balance;
            }
        }

        public Account()
        {
            _balance = 1000;
        }

        public void WithDraw(string name,object money)
        {
            if ((int)money <= _balance)
            {
                Thread.Sleep(2000);
                _balance = _balance - (int)money;
                Console.WriteLine("{0} 取钱成功!余额={1}", name, _balance);
            }
            else
            {
                Console.WriteLine("{0} 取钱失败!余额不足!", name);
            }
        }
    }

//调用:
            var account = new Account();
            Parallel.Invoke(() =>
            {
                account.WithDraw("张三",600);

            }, () =>
            {
                account.WithDraw("李四",600);
            });

6.MethodImplAttribute--使整个方法上锁,直到方法返回,才释放锁

示例:

    public class Account
    {
        private static int _balance;
        public int Blance
        {
            get
            {
                return _balance;
            }
        }

        public Account()
        {
            _balance = 1000;
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void WithDraw(string name,object money)
        {
            if ((int)money <= _balance)
            {
                Thread.Sleep(2000);
                _balance = _balance - (int)money;
                Console.WriteLine("{0} 取钱成功!余额={1}", name, _balance);
            }
            else
            {
                Console.WriteLine("{0} 取钱失败!余额不足!", name);
            }
        }
    }

//调用
            var account = new Account();
            Parallel.Invoke(() =>
            {
                account.WithDraw("张三",600);

            }, () =>
            {
                account.WithDraw("李四",600);
            });

7.AutoResetEvent、ManualResetEvent、ManualResetEventSlim--调用WaitOne、WaitAny或WaitAll来使线程等待事件,调用Set方法发送信号,事件将变为终止状态,等待的线程被唤醒

示例:

            AutoResetEvent arEvent = new AutoResetEvent(false);//默认为无信号,处于非终止状态
            Task.Factory.StartNew((o) => {
                for (int i = 1; i <= 10; i++)
                {
                    Console.WriteLine("循环第{0}次",i);
                }
                arEvent.Set();//发送信号,处于终止状态
            },arEvent);

            arEvent.WaitOne();//等待信号,收到信号后则继续下面的执行

            Console.WriteLine("我是主线程,我继续执行!");
            Console.Read();

8.Sempaphore、SemaphoreSlim(不可跨进程)--信号量,可实现线程、进程间同步

示例:

    public class WashRoom
    {
        private readonly Semaphore sem;

        public WashRoom(int maxUseableCount)
        {
            sem = new Semaphore(maxUseableCount, maxUseableCount, "WC");
        }

        public void Use(int i)
        {
            Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("第{0}个人等待进入", i);
                    // WaitOne:如果还有“空位”,则占位,如果没有空位,则等待;
                    sem.WaitOne();
                    Console.WriteLine("第{0}个人成功进入,使用中", i);
                    // 模拟线程执行了一些操作
                    Thread.Sleep(100);
                    Console.WriteLine("第{0}个人用完,离开了", i);
                    // Release:释放一个“空位”
                    sem.Release();
                });
        }
    }

//调用:
            var wc = new WashRoom(5);
            for (int i = 1; i <= 7; i++)
            {
                wc.Use(i);
            }

9.Barrier--屏障,使多个任务能够采用并行方式依据某种算法在多个阶段中协同工作,即:将一个阶段的事情分成多个线程来异步执行,执行完毕后再同时进入下一个阶段

示例:

            int taskSize = 5;
            Barrier barrier = new Barrier(taskSize, (b) =>
            {
                Console.WriteLine(string.Format("{0}当前阶段编号:{1}{0}", "-".PadRight(15, ‘-‘), b.CurrentPhaseNumber));
            });

            var tasks = new Task[taskSize];

            for (int i = 0; i < taskSize; i++)
            {
                tasks[i] = Task.Factory.StartNew((n) =>
                {
                    Console.WriteLine("Task : #{0}   ---->  处理了第一部份数据。", n);
                    barrier.SignalAndWait();

                    Console.WriteLine("Task : #{0}   ---->  处理了第二部份数据。", n);
                    barrier.SignalAndWait();

                    Console.WriteLine("Task : #{0}   ---->  处理了第三部份数据。", n);
                    barrier.SignalAndWait();

                }, i);
            }

            Task.WaitAll(tasks);

10.SpinLock--自旋锁,仅限锁定的时间较短

示例:

            SpinLock sLock = new SpinLock();
            int num = 0;
            Action action = () =>
            {
                bool lockTaken = false;
                for (int i = 0; i < 10; i++)
                {
                    lockTaken = false;
                    try
                    {
                        sLock.Enter(ref lockTaken);
                        Console.WriteLine("{0}+1={1} ---线程ID:[{2}]", num, ++num,Thread.CurrentThread.ManagedThreadId);
                        Thread.Sleep(new Random().Next(9));
                    }
                    finally
                    {
                        //真正获取之后,才释放
                        if (lockTaken) sLock.Exit();
                    }
                }
            };

//多线程调用:
            Parallel.Invoke(action, action, action);
            Console.WriteLine("合计:{0}", num);

11.SpinWait--自旋等待,轻量级

            Thread.Sleep(1000);//线程等待1S;
            Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));

            SpinWait.SpinUntil(() => false, 1000);//自旋等待1S
            Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));

            Thread.SpinWait(100000);//指定CPU的循环次数,时间间隔处决于处理器的运行速度,一般不建议使用
            Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));

12.CountdownEvent--与Sempaphore功能类似,但CountdownEvent支持动态调整信号计数

示例:

        static void TimeLimitShopping(int custCount,int times,CountdownEvent countdown)
        {
            var customers = Enumerable.Range(1, custCount);
            foreach (var customer in customers)
            {
                int currentCustomer = customer;
               Task.Factory.StartNew(()=>
                {
                    SpinWait.SpinUntil(() => false, 1000);
                    Console.WriteLine("第{0}波客户购买情况:Customer-{1}-已购买.", times, currentCustomer);
                    countdown.Signal();
                });
                //countdown.AddCount();
            }
        }

//调用:
var countdown = new CountdownEvent(5);
                TimeLimitShopping(5, 1, countdown);
                countdown.Wait();

                countdown.Reset(10);
                TimeLimitShopping(10, 2, countdown);
                countdown.Wait();

                countdown.Reset(20);
                TimeLimitShopping(20, 3, countdown);
                countdown.Wait();

最后分享在System.Collections.Concurrent命名空间下的几个并发集合类:

ConcurrentBag<T>:表示线程安全的无序集合;

ConcurrentDictionary<T>:表示线程安全的多个键值对集合;

ConcurrentQueue<T>:表示线程安全的先进先出集合;

ConcurrentStack<T>:表示线程安全的后进先出集合;

线程的几个状态(以下图片来源于这篇文章:http://www.cnblogs.com/edisonchou/p/4848131.html):

参考以下相关文章:

归纳一下:C#线程同步的几种方法

C#编程总结(三)线程同步

时间: 2024-08-25 13:58:38

C#多线程技术总结(同步)的相关文章

OS X 和iOS 中的多线程技术(上)

OS X 和iOS 中的多线程技术(上) 本文梳理了OS X 和iOS 系统中提供的多线程技术.并且对这些技术的使用给出了一些实用的建议. 多线程的目的:通过并发执行提高 CPU 的使用效率,进而提供程序运行效率. 1.线程和进程 进程 什么是进程 进程是指在计算机系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行中其专用且受保护的内存空间内 比如同时打开 Xcode .Safari ,系统就会分别启动两个进程 通过活动监视器可以查看Mac系统中所开启的进程 线程 什么是线程 一

C# 多线程(二) 线程同步基础

本系列的第一篇简单介绍了线程的概念以及对线程的一些简单的操作,从这一篇开始讲解线程同步,线程同步是多线程技术的难点.线程同步基础由以下几个部分内容组成 1.同步要领(Synchronization Essentials) 2.锁(Locking) 3.线程安全(Thread Safety) 4.事件等待句柄(Signaling with Event Wait Handles) 5.同步上下文(Synchronization Contexts) 同步要领(Synchronization Essen

Java多线程技术学习笔记(二)

目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和wait的区别 停止线程的方式 守护线程 线程的其他知识点 一.线程间的通信示例 返目录回 多个线程在处理同一资源,任务却不同. 假设有一堆货物,有一辆车把这批货物往仓库里面运,另外一辆车把前一辆车运进仓库的货物往外面运.这里货物就是同一资源,但是两辆车的任务却不同,一个是往里运,一个是往外运. 下面

iOS多线程技术

说明:开发技术大同小异,帖子写出来不是为了晒的,只是一个学习记录过程,有错误欢迎指正,喜欢喷人的请滚蛋. 一.实现方案 在iOS中有三种多线程实现技术,它们分别是NSThread.GCD .NSOperation. NSThread:基于OC编写,更加面向对象,可直接操作线程对象,需要程序员手动管理线程生命周期,开发中偶尔使用. GCD:基于c语言编写,旨在替代NSThread线程技术,能充分利用设备的多核,系统自动管理线程生命周期,开发中经常使用. NSOperation:底层基于GCD封装的

VC中利用多线程技术实现线程之间的通信

文章来源:[url]http://www.programfan.com/article/showarticle.asp?id=2951[/url] 当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义.现在的大型应用软件无一不是多线程多任务处理,单线程的软件是不可想象的.

C# 多线程(二) 线程同步基础(上)

本系列的第一篇简单介绍了线程的概念以及对线程的一些简单的操作,从这一篇开始讲解线程同步,线程同步是多线程技术的难点.线程同步基础由以下几个部分内容组成 1.同步要领(Synchronization Essentials) 2.锁(Locking) 3.线程安全(Thread Safety) 4.事件等待句柄(Signaling with Event Wait Handles) 5.同步上下文(Synchronization Contexts) 同步要领(Synchronization Essen

C# 多线程之线程同步

多线程间应尽量避免同步问题,最好不要线程间共享数据.如果必须要共享数据,就需要使用同步技术,确保一次只有一个线程访问和改变共享状态. 一::lock语句 lock语句事设置锁定和接触锁定的一种简单方法.其语法非常简单: lock (obj) { // 需要发生同步的代码区 } 将共享数据的操作代码,放在上述的"{...}"区域内.锁定的对象(obj)必须是引用类型,如果锁定一个值类型,实际是锁定了它的一个副本,并没有实现锁定功能. 一般地,被锁定对象需要被创建为 私有 只读 引用类型:

iOS的三种多线程技术NSThread/NSOperation/GCD

1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的"并发"技术,使得程序员可以不再去关心线程的具体使用问题 NSOperation/NSOperationQueue 面向对象的线程技术 GCD -- Grand Central Dispatch(派发) 是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术. 以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,

iOS的多线程技术

iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题 ØNSOperation/NSOperationQueue 面向对象的线程技术 ØGCD —— Grand Central Dispatch(派发) 是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术 以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Appl

iOS- NSThread/NSOperation/GCD 三种多线程技术的对比及实现 -- 转

1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题 ØNSOperation/NSOperationQueue 面向对象的线程技术 ØGCD —— Grand Central Dispatch(派发) 是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术 以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Ap