惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
Cisco Talos Blog
Cisco Talos Blog
C
Check Point Blog
博客园_首页
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Martin Fowler
Martin Fowler
Recorded Future
Recorded Future
S
Security @ Cisco Blogs
L
LINUX DO - 最新话题
博客园 - 司徒正美
P
Privacy International News Feed
G
Google Developers Blog
I
Intezer
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
C
Cybersecurity and Infrastructure Security Agency CISA
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Scott Helme
Scott Helme
K
Kaspersky official blog
I
InfoQ
Y
Y Combinator Blog
T
The Blog of Author Tim Ferriss
Webroot Blog
Webroot Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
大猫的无限游戏
大猫的无限游戏
D
Docker
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
Microsoft Azure Blog
Microsoft Azure Blog
Spread Privacy
Spread Privacy
量子位
H
Hacker News: Front Page
Simon Willison's Weblog
Simon Willison's Weblog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
SecWiki News
SecWiki News
S
Security Affairs
Latest news
Latest news
人人都是产品经理
人人都是产品经理
C
CERT Recently Published Vulnerability Notes
S
Security Archives - TechRepublic
V
Visual Studio Blog
T
Troy Hunt's Blog
S
Secure Thoughts
F
Fortinet All Blogs
V
V2EX
The Register - Security
The Register - Security
J
Java Code Geeks
MongoDB | Blog
MongoDB | Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO

博客园 - 王庆

crosstool-ng搭建交叉编译环境注意事项 多重继承及虚继承中对象内存的分布 编写和调试Android下JNI程序流程 eclipse xml文件中按alt+/没有提示信息 Android NDK 工具链的使用方法(Standalone Toolchain) 编译Android VNC Server 使用gdb和gdbserver调试Android C/C++程序 openssl在多平台和多语言之间进行RSA加解密注意事项 LINUX开发使用的3个远程工具 NDK 链接第三方静态库的方法 动态生成程序集和类型 关于线程池的一段代码 理解ParseChildren用法 快速查找ASP.NET产生的临时文件 捕获ASP.NET程序发生的异常 Synchronized vs SyncRoot Exception vs ApplicationException 【转】Hashtable,ListDictionary,HybridDictionary比较 C#多线程之Thread
Monitor用法
王庆 · 2008-07-07 · via 博客园 - 王庆

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