c#多线程之monitor和lock

来源:互联网 发布:php 设置时区 编辑:程序博客网 时间:2024/05/01 21:51

monitor关键字可以锁定对象,lock为互斥锁,可以锁代码,但二者的实质一样的,lock也是使用monitor的enter和exit实现的,实质上只是将该对象作为一个标识而已,当一个线程尝试进入到被lock或monitor锁住的代码,都需要把当前lock对象和已存在的锁对象进行一一对比,使用object.referenceEquals()。

monitor类所以名义上说的是锁一个对象,但实际上仍然只是锁enter和exit之间的代码,而并不是锁该对象的所有方法,详见如下一实例:

线程tr2的执行函数使用monitor.enter和exit锁住了cell对象,但其中间执行的代码和cell对象并没有关系,而tr1线程直接使用cell对象的方法,在两个线程同时进行的时候,我们发现线程tr2的锁并不影响tr1对该对象方法的调用,输出结果如下,read和write交替输出。


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

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            Cell cell = new Cell();
            CellRead cr = new CellRead(cell);
            CellWrite cw = new CellWrite(cell);

            Thread tr1 = new Thread(new ThreadStart(cr.Read));
            Thread tr2 = new Thread(new ThreadStart(cw.Write));

            tr1.Name = "tr1";
            tr2.Name = "tr2";

            tr2.Start();
            tr1.Start();

            Console.Read();

        }
    }

    class Cell
    {
        public void read2()
        {
            Console.WriteLine("read2");
        }

        public void write2()
        {
            Console.WriteLine("write2");
        }
    }

    class CellRead
    {
        Cell cell;
        public CellRead(Cell cell)
        {
            this.cell = cell;
        }

        public void Read()
        {
            //Monitor.Enter(cell);              //线程tr1并没有尝试锁住cell

            for (int i = 1; i < 200; i++)
            {
                cell.read2();
            }

            //Monitor.Exit(cell);
        }
    }

    class CellWrite
    {
        Cell cell;
        public CellWrite(Cell cell)
        {
            this.cell = cell;
        }

        public void Write()
        {
            Monitor.Enter(cell);
            for (int i = 1; i < 200; i++)
            {
                Console.WriteLine("write");
            }
            Monitor.Exit(cell);
        }
    }
}

但如果我们把CellRead类的read方法的锁注释打开,再执行,则结果就只能是其中read线程必须等write线程锁解开后才能执行了,结果如下:


总结,不管是monitor还是lock,都是通过查看对象是否被锁来确定是否可以进入代码的,所以值类型不能作为锁的对象,全局对象很容易被多个线程当做锁对象,也需要谨慎使用,如果一个对象内有多个目的不同代码块,不要都使用lock(this),这将导致每次只能执行其中一个代码块,但实际并不是所有都是互斥的。
原创粉丝点击