C#多线程——多线程访问共同的代码或者对象

C#多线程:互斥访问与Lock/Monitor机制
本文介绍了C#中多线程访问共享资源时可能导致的数据混乱问题,强调了互斥访问的重要性。通过Lock和Monitor两种方式实现线程间的互斥,确保同一时刻只有一个线程能访问特定代码或变量。Monitor维护了预备队列和等待队列,释放锁时会唤醒等待队列中的线程。示例代码展示了Lock和Monitor的用法。

多线程对共同资源的访问,往往会造成数据的混乱和不可预料的结果,因此一般需要加锁访问进行互斥访问。

所谓“互斥访问”是指,一段代码或者公共变量,在一个时刻只允许一个线程去访问,其他的线程需要等待,直到改线程处理完毕并通知下一个等待的线程去处理。

1、可以用“Lock”来提供代码的互斥访问:

lock (一个类的示例、静态变量的类名)
{
        // 代码
}

2、可以用“Monitor”来提供变量的互斥访问:

int money;
Monitor.Enter(money);
// money++或者money--;
Monitor.Exit(money);

Monitor的工作原理是:Monitor维护了两个队列,一个是预备队列,其中保存准备获取锁的线程;另一个是等待队列,保存正在等待这个对象状态改变的线程。当锁被一个线程释放时,调用Monitor.Pulse()方法,将等待队列中的第一个线程放到预备队列中。

 

下面是一个使用Lock和Monitor的例子:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace Demo
{
    public class ProductClass
    {
        int products;
        bool enableGet = false;   // If ture, consumer can get product, otherwise producer is producing.

        public int GetProducts()
        {
            lock (this)
            {
                if (!enableGet)
                {
                    try
                    {
                        Monitor.Wait(this);
                    }
                    catch (SynchronizationLockException ex)
                    {
                        Console.WriteLine("[SynchronizationLockException Error]: " + ex.ToString());
                    }
                    catch (ThreadInterruptedException ex)
                    {
                        Console.WriteLine("[ThreadInterruptedException Error]: " + ex.ToString());
                    }
                }
                Console.WriteLine("Consume: {0}", products);

                // Reset to be false after getting products.
                enableGet = false;

                // Notify producing thread to produce products
                Monitor.Pulse(this);
            }
            return products;
        }

        public void ProduceProducts(int products)
        {
            lock (this)
            {
                if (enableGet)
                {
                    try
                    {
                        Monitor.Wait(this);
                    }
                    catch (SynchronizationLockException ex)
                    {
                        Console.WriteLine("[SynchronizationLockException Error]: " + ex.ToString());
                    }
                    catch (ThreadInterruptedException ex)
                    {
                        Console.WriteLine("[ThreadInterruptedException Error]: " + ex.ToString());
                    }
                }
                this.products = products;
                Console.WriteLine("Produce: {0}", products);
                enableGet = true;
                Monitor.Pulse(this);
            }
        }
    }

    public class Producer
    {
        ProductClass aProductClass;
        int produceTimes = 1;

        public Producer(ProductClass aProductClass, int produceTimes)
        {
            this.aProductClass = aProductClass;
            this.produceTimes = produceTimes;
        }

        public void ThreadRun()
        {
            for (int i = 0; i < produceTimes; i++)
            {
                aProductClass.ProduceProducts(i);
            }
        }
    }

    public class Consumer
    {
        ProductClass aProductClass;
        int getProductTimes = 1;

        public Consumer(ProductClass aProductClass, int getProductTimes)
        {
            this.aProductClass = aProductClass;
            this.getProductTimes = getProductTimes;
        }

        public void ThreadRun()
        {
            int returnValue;
            for (int i = 0; i < getProductTimes; i++)
            {
                returnValue = aProductClass.GetProducts();
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ProductClass aProductClass = new ProductClass();
            Producer aProducer = new Producer(aProductClass, 20);
            Consumer aConsumer = new Consumer(aProductClass, 20);

            Thread produceThread = new Thread(new ThreadStart(aProducer.ThreadRun));
            Thread consumeThread = new Thread(new ThreadStart(aConsumer.ThreadRun));

            try
            {
                produceThread.Start();
                consumeThread.Start();
                produceThread.Join();
                consumeThread.Join();
                Console.ReadLine();
            }
            catch (ThreadStateException ex)
            {
                Console.WriteLine("[ThreadStateException Error]: " + ex.ToString());
            }
            catch (ThreadInterruptedException ex)
            {
                Console.WriteLine("[ThreadInterruptedException Error]: " + ex.ToString());
            }
        }
    }
}


 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值