多进程、多线程、同步写

Windows编程中不建议创建进程(进程创建的开销不容忽视),若需要大量创建进程,最好切换到Linux系统;Windows偏向多线程大量对面资源争抢与同步的问题。
在面向多核的服务器端编程中,需要习惯多进程而非多线程。(在CPU多核情况下,多线程在性能上不如多进程);Linux偏向进程间通信的方法。

进程与线程比较

比较 进程 线程
定义 调度:线程作为调度和分配的基本单位,不拥有系统资源,但可以访问隶属于进程的资源;
并发性:进程之间可以并发执行;
系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销大;
调度:进程作为拥有资源的基本独立单位;
并发性:同一个进程的多个线程之间也可并发执行;
系统开销:创建或撤消线程时的开销小;
通信定义 进程通信一般指不同进程间的线程进行通讯。 线程通信一般指同一进程内的线程进行通讯。
通信方式 IPC(Inter Process Communication)协程
管道(Pipe) 多用于父子关系的进程;无名管道用来在操作系统进程间进行较大数据量通信;有名管道用来使服务器通过网络与多个用户交互;
信号(Signal);
消息队列 用来在客户端修改了共享内存后通知服务器读取;
共享内存 用来传递数据;
信号量(Semaphore) 用于生产者/消费者;
套接字(Socket);
全局变量、自定义消息响应等。
同步机制 Mutex(互斥)、Semaphore等可以跨进程使用。 临界区、互斥、信号量、事件等。
同步方法 阻塞:Sleep(使调用线程阻塞)、Join、EndInvoke(使另外一个线程阻塞);
加锁:lock(object),允许同一时间只有一个线程执行;
Monitors,lock的内部实现;
互斥锁(Mutex),可以在不同的进程间实现线程同步;
信号和句柄:AutoResetEvent, ManualResetEvent;
Interlocked,为多线程共享的变量提供原子操作;
ReaderWriterLock,允许同一时间有多个线程可以执行读操作,或者只有一个有排它锁的线程执行写操作。

同步机制

同步机制四原则:空闲让进、忙则等待、有限等待、让权等待。进程之间的同步方式比线程间的同步方式选择小。能用多进程(考虑程序稳定性)方便的解决问题就不要使用多线程。需要频繁创建销毁的(Web服务器)、需要进行大量计算的(图像处理、算法处理)、强相关的处理、多核分布的场景等优先使用线程。

复杂多线程环境下同步写测试

        static int _RunCnt = 1000;
        static int _SumCount = 0;
        static int _WriteCount = 0;
        static int _FailedCount = 0;

        static void Main(string[] args)
        {
            int m, n;
            ThreadPool.GetMinThreads(out m, out n);
            Console.WriteLine("WorkerThreads-Min:{0} CompletionPortThreads-Min:{1}", m, n);
            ThreadPool.GetMaxThreads(out m, out n);
            Console.WriteLine("WorkerThreads-Max:{0} CompletionPortThreads-Max:{1}", m, n);

            // 往线程池里添加一个任务,迭代写入N个任务
            _SumCount += _RunCnt;
            ThreadPool.QueueUserWorkItem(obj =>
            {
                Parallel.For(0, _RunCnt, e =>
                {
                    WriteInfo();
                });
            });
            // 在新的线程里,添加N个任务
            _SumCount += _RunCnt;
            Task.Run(() =>
            {
                Parallel.For(0, _RunCnt, e =>
                {
                    ThreadPool.QueueUserWorkItem(obj =>
                    {
                        WriteInfo();
                    });
                });
            });
            // 添加N个任务到线程池
            _SumCount += _RunCnt;
            Parallel.For(0, _RunCnt, e =>
            {
                ThreadPool.QueueUserWorkItem(obj =>
                {
                    WriteInfo();
                });
            });
            // 在当前线程里,迭代写入N个任务
            _SumCount += _RunCnt;
            Parallel.For(0, _RunCnt, e =>
            {
                WriteInfo();
            });

            while (true)
            {
                Console.WriteLine("Sum Count:{0}.\t\tWrited Count:{1}.\tFailed Count:{2}.", _SumCount, _WriteCount, _FailedCount);
                Console.ReadKey();

            }
        }

        private static void WriteInfo()
        {
            try
            {
                // Do Sth
                _WriteCount++;
            }
            catch (Exception ex)
            {
                string str = ex.Message;
                _FailedCount++;
            }
            finally
            {
                // Release
            }            
        }

猜你喜欢

转载自www.cnblogs.com/wesson2019-blog/p/12126265.html