A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Invoker 中级黑马   /  2014-4-26 17:48  /  1603 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 Invoker 于 2014-4-27 12:52 编辑

lock和monitor之间有什么区别? 什么情况下要使用他们

评分

参与人数 1技术分 +1 收起 理由
张旭辉 + 1 神马都是浮云

查看全部评分

5 个回复

倒序浏览
lock和Monitor是.NET用一个特殊结构实现的,Monitor对象是完全托管的、完全可移植的,并且在操作系统资源要求方面可能更为有效,同步速度较快,但不能跨进程同步。
lock(Monitor.Enter和Monitor.Exit方法的封装),主要作用是锁定临界区,使临界区代码只能被获得锁的线程执行。Monitor.Wait和Monitor.Pulse用于线程同步,类似信号操作,个人感觉使用比较复杂,容易造成死锁。
回复 使用道具 举报
Lock和Monitor都是对被操作对象同步控制的方法



Lock 是 Monitor的简化版本,IL

callvirt ...Monitor.Enter(object)
...
leave.s
....
callvirt ...Monitor.Exit(object)

Lock 只能对引用对象加锁

Lock锁定区间内可以对锁定值修改而不发生运行时错误,通常也会采用此种修改方式。这种方式又有点类同于使用Monitor.Wait 取得资源,并对这个资源进行操作。

lock (lockObj)

{

    lockObj = newObj;

}



Monitor 可以对值类型加锁,实际上是在调用Monitor.Enter时对值类型装箱了

Monitor在锁定区域内不能对被锁对象的值进行修改,运行时抱错“从不同步的代码块中调用了对象同步方法”

int lockInt = 0;

try

{

    Monitor.Enter(lockInt);

    lockInt = newValue;

}

catch

{



}

finally

{

    Monitor.Exit(newValue);

}

Monitor 相对Lock有其他一些复杂功能

Monitor.TryEnter

//Try to add an element to the queue.

//Add the element to the queue only if the queue object is unlocked.

public bool AddElementWithoutWait(object qValue)

{

    //Determine whether the queue is locked

    if (!Monitor.TryEnter(m_inputQueue))

        return false;

    m_inputQueue.Enqueue(qValue);



    Monitor.Exit(m_inputQueue);

    return true;

}



//Try to add an element to the queue.

//Add the element to the queue only if during the specified time the queue object will be unlocked.

public bool WaitToAddElement(object qValue, int waitTime)

{

    //Wait while the queue is locked.

    if (!Monitor.TryEnter(m_inputQueue, waitTime))

        return false;

    m_inputQueue.Enqueue(qValue);

    Monitor.Exit(m_inputQueue);



    return true;

}

Monitor.Wait

Monitor.Pulse

Monitor.PulseAll

Monitor.Wait(m_smplQueue);

//Push one element.

m_smplQueue.Enqueue(counter);

//Release the waiting thread.

Monitor.Pulse(m_smplQueue);

Monitor.PulseAll(m_smplQueue);

Wait: 等待得到被锁对象,可以对被锁对象进行操作

Pulse: 释放当前锁定操作对象,下一个等待该对象的Wait将得到对象的使用权
PulseAll:释放当前锁定对象,所有正在等待该对象得Wait将同时得到释放(进入下一行代码,可以认为不在对该对象进行同步控制)

评分

参与人数 1技术分 +1 收起 理由
张旭辉 + 1

查看全部评分

回复 使用道具 举报
Mekor 发表于 2014-4-26 22:10
Lock和Monitor都是对被操作对象同步控制的方法


你这个只介绍了基础用法吧 我还希望能有更深入的一些东西
回复 使用道具 举报
嘴角上揚ぃ读不 发表于 2014-4-26 22:06
lock和Monitor是.NET用一个特殊结构实现的,Monitor对象是完全托管的、完全可移植的,并且在操作系统资源 ...

同步速度是什么呢
回复 使用道具 举报
与 lock 关键字类似,监视器防止多个线程同时执行代码块。Enter 方法允许一个且仅一个线程继续执行后面的语句;其他所有线程都将被阻止,直到执行语句的线程调用 Exit。这与使用 lock 关键字一样。事实上,lock 关键字就是用 Monitor 类来实现的。例如:
lock (x)
{
    DoSomething();
}
这等效于:
System.Object obj = (System.Object)x;
System.Threading.Monitor.Enter(obj);
try
{
    DoSomething();
}
finally
{
    System.Threading.Monitor.Exit(obj);
}
使用 lock 关键字通常比直接使用 Monitor 类更可取,一方面是因为 lock 更简洁,另一方面是因为 lock 确保了即使受保护的代码引发异常,也可以释放基础监视器。这是通过 finally 关键字来实现的,无论是否引发异常它都执行关联的代码块。

评分

参与人数 1技术分 +1 收起 理由
张旭辉 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马