Monitor用法

Monitor 类通过向单个线程授予对象锁来控制对对象的访问,提供同步对对象的访问的机制

Monitor 具有以下功能:
它根据需要与某个对象相关联。
它是未绑定的,也就是说可以直接从任何上下文调用它。
不能创建 Monitor 类的实例。

将为每个同步对象来维护以下信息:
对当前持有锁的线程的引用。
对就绪队列的引用,它包含准备获取锁的线程。
对等待队列的引用,它包含正在等待锁定对象状态变化通知的线程。

Monitor有几个主要的方法,我们需要了解
1.Monitor.Enter和Monitor.Exit
他们两个是一起的,我们在一个方法中,如果调用了Monitor.Enter,那么就必须有相应的Monitory.Exit方法与之对应。这两个方法用于锁定对象和取消锁定对象,在平时的使用中,我们一般用lock取代他们。

2.Monitor.Wait方法
当线程调用 Wait 时,它释放对象的锁并进入对象的等待队列,对象的就绪队列中的下一个线程(如果有)获取锁并拥有对对象的独占使用。

3.Monitor.Pulse方法
当前线程调用此方法以便向队列中的下一个线程发出锁的信号。接收到脉冲后,等待线程就被移动到就绪队列中。在调用 Pulse 的线程释放锁后,就绪队列中的下一个线程(不一定是接收到脉冲的线程)将获得该锁。

下面的代码示例说明如何使用以上方法。

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

namespace  ConsoleApplication6
{
    
public class Cell
    
{
        
int cellContents; // Cell对象里边的内容
        bool readerFlag = false// 状态标志,为true时可以读取,为false则正在写入
        public int ReadFromCell()
        
{
            
lock (this// Lock关键字保证了什么,请大家看前面对lock的介绍
            {
                
if (!readerFlag)//如果现在不可读取
                {
                    
try
                    
{
                        
//等待WriteToCell方法中调用Monitor.Pulse()方法
                        Monitor.Wait(this);
                    }

                    
catch (SynchronizationLockException e)
                    
{
                        Console.WriteLine(e);
                    }

                    
catch (ThreadInterruptedException e)
                    
{
                        Console.WriteLine(e);
                    }

                }

                Console.WriteLine(
"Consume: {0}", cellContents);
                readerFlag 
= false//重置readerFlag标志,表示消费行为已经完成
                Monitor.Pulse(this); //通知WriteToCell()方法(该方法在另外一个线程中执行,等待中)
            }

            
return cellContents;
        }


        
public void WriteToCell(int n)
        
{
            
lock (this)
            
{
                
if (readerFlag)
                
{
                    
try
                    
{
                        Monitor.Wait(
this);
                    }

                    
catch (SynchronizationLockException e)
                    
{
                        
//当同步方法(指Monitor类除Enter之外的方法)在非同步的代码区被调用
                        Console.WriteLine(e);
                    }

                    
catch (ThreadInterruptedException e)
                    
{
                        
//当线程在等待状态的时候中止 
                        Console.WriteLine(e);
                    }

                }

                cellContents 
= n;
                Console.WriteLine(
"Produce: {0}", cellContents);
                readerFlag 
= true;
                Monitor.Pulse(
this); //通知另外一个线程中正在等待的ReadFromCell()方法
            }

        }

    }


    
public class CellProd
    
{
        Cell cell; 
// 被操作的Cell对象
        int quantity = 1// 生产者生产次数,初始化为1 

        
public CellProd(Cell box, int request)
        
{
            
//构造函数
            cell = box;
            quantity 
= request;
        }

        
public void ThreadRun()
        
{
            
for (int looper = 1; looper <= quantity; looper++)
                cell.WriteToCell(looper); 
//生产者向操作对象写入信息
        }

    }


    
public class CellCons
    
{
        Cell cell;
        
int quantity = 1;

        
public CellCons(Cell box, int request)
        
{
            cell 
= box;
            quantity 
= request;
        }

        
public void ThreadRun()
        
{
            
int valReturned;
            
for (int looper = 1; looper <= quantity; looper++)
                valReturned 
= cell.ReadFromCell();//消费者从操作对象中读取信息
        }

    }


    
public class MonitorSample
    
{
        
public static void Main(String[] args)
        
{
            
int result = 0;
            
//一个标志位,如果是0表示程序没有出错,如果是1表明有错误发生
            Cell cell = new Cell();

            
//下面使用cell初始化CellProd和CellCons两个类,生产和消费次数均为20次
            CellProd prod = new CellProd(cell, 5);
            CellCons cons 
= new CellCons(cell, 5);

            Thread producer 
= new Thread(new ThreadStart(prod.ThreadRun));
            Thread consumer 
= new Thread(new ThreadStart(cons.ThreadRun));
            
//生产者线程和消费者线程都已经被创建,但是没有开始执行 

            
try
            
{
                producer.Start();
                consumer.Start();

                producer.Join();
                consumer.Join();
                Console.ReadLine();
            }

            
catch (ThreadStateException e)
            
{
                
//当线程因为所处状态的原因而不能执行被请求的操作
                Console.WriteLine(e);
                result 
= 1;
            }

            
catch (ThreadInterruptedException e)
            
{
                
//当线程在等待状态的时候中止
                Console.WriteLine(e);
                result 
= 1;
            }

            
//尽管Main()函数没有返回值,但下面这条语句可以向父进程返回执行结果
            Environment.ExitCode = result;
        }

    }

}

  Result:

Produce: 1
Consume: 1
Produce: 2
Consume: 2
Produce: 3
Consume: 3
Produce: 4
Consume: 4
Produce: 5
Consume: 5

转载于:https://www.cnblogs.com/fengfeng/archive/2008/07/07/1237528.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值