锁语句在幕后有什么作用?

发布于 2024-11-07 09:47:56 字数 249 浏览 5 评论 0原文

我发现,对于使用非线程安全的对象,我们用这样的锁包装代码:

private static readonly Object obj = new Object();

lock (obj)
{
    // thread unsafe code
}

那么,当多个线程访问相同的代码时会发生什么(假设它在 ASP.NET Web 应用程序中运行)。他们在排队吗?如果是这样,他们会等多久?

使用锁对性能有何影响?

I see that for using objects which are not thread safe we wrap the code with a lock like this:

private static readonly Object obj = new Object();

lock (obj)
{
    // thread unsafe code
}

So, what happens when multiple threads access the same code (let's assume that it is running in a ASP.NET web application). Are they queued? If so how long will they wait?

What is the performance impact because of using locks?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

温柔戏命师 2024-11-14 09:47:56

lock 语句由 C# 3.0 翻译为以下内容:

var temp = obj;

Monitor.Enter(temp);

try
{
    // body
}
finally
{
    Monitor.Exit(temp);
}

在 C# 4.0 中 这已更改,现在生成如下:

bool lockWasTaken = false;
var temp = obj;
try
{
    Monitor.Enter(temp, ref lockWasTaken);
    // body
}
finally
{
    if (lockWasTaken)
    {
        Monitor.Exit(temp); 
    }
}

您可以找到有关 Monitor.Enter 功能的更多信息此处。引用MSDN:

使用Enter获取监视器
作为参数传递的对象。如果
另一个线程已执行 Enter
在对象上但尚未执行
对应的Exit,当前
线程将阻塞,直到另一个线程
线程释放对象。这是
同一线程调用合法
多次输入而不使用它
阻塞;然而,同等数量的
必须先调用 Exit 调用
其他线程正在等待该对象
将解锁。

Monitor.Enter 方法将无限等待;它不会超时。

The lock statement is translated by C# 3.0 to the following:

var temp = obj;

Monitor.Enter(temp);

try
{
    // body
}
finally
{
    Monitor.Exit(temp);
}

In C# 4.0 this has changed and it is now generated as follows:

bool lockWasTaken = false;
var temp = obj;
try
{
    Monitor.Enter(temp, ref lockWasTaken);
    // body
}
finally
{
    if (lockWasTaken)
    {
        Monitor.Exit(temp); 
    }
}

You can find more info about what Monitor.Enter does here. To quote MSDN:

Use Enter to acquire the Monitor on
the object passed as the parameter. If
another thread has executed an Enter
on the object but has not yet executed
the corresponding Exit, the current
thread will block until the other
thread releases the object. It is
legal for the same thread to invoke
Enter more than once without it
blocking; however, an equal number of
Exit calls must be invoked before
other threads waiting on the object
will unblock.

The Monitor.Enter method will wait infinitely; it will not time out.

南渊 2024-11-14 09:47:56

它比您想象的要简单 -

根据Microsoft
lock 关键字可确保一个线程不会在另一个线程处于代码临界区时进入该临界区。如果另一个线程尝试输入锁定的代码,它将等待、阻塞,直到该对象被释放。

lock 关键字调用 在块的开头输入在块末尾退出lock 关键字实际上处理 Monitor 后端类。

例如:

private static readonly Object obj = new Object();

lock (obj)
{
    // critical section
}

在上面的代码中,首先线程进入临界区,然后它会锁定obj。当另一个线程尝试进入时,它也会尝试锁定已经被第一个线程锁定的 obj。第二个线程必须等待第一个线程释放obj。当第一个线程离开时,另一个线程将锁定 obj 并进入临界区。

Its simpler than you think-

According to Microsoft:
The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released.

The lock keyword calls Enter at the start of the block and Exit at the end of the block. lock keyword actually handles Monitor class at back end.

For example:

private static readonly Object obj = new Object();

lock (obj)
{
    // critical section
}

In the above code, first the thread enters a critical section, and then it will lock obj. When another thread tries to enter, it will also try to lock obj, which is already locked by the first thread. Second thread will have to wait for the first thread to release obj. When the first thread leaves, then another thread will lock obj and will enter the critical section.

夕嗳→ 2024-11-14 09:47:56

不,它们没有排队,它们正在休眠

一种形式的锁定语句

lock (x) ... 

,其中 x 是引用类型的表达式,恰好相当于

var temp = x;
System.Threading.Monitor.Enter(temp); 
try { ... } 
finally { System.Threading.Monitor.Exit(temp); }

您只需要知道它们正在互相等待,并且只有一个线程会进入锁定块,其他人会等待...

监视器完全用.net编写,因此它足够快,另请参阅类监视器反射器了解更多详情

No, they are not queued, they are sleeping

A lock statement of the form

lock (x) ... 

where x is an expression of a reference-type, is precisely equivalent to

var temp = x;
System.Threading.Monitor.Enter(temp); 
try { ... } 
finally { System.Threading.Monitor.Exit(temp); }

You just need to know that they are waiting to each other, and only one thread will enter to lock block, the others will wait...

Monitor is written fully in .net so it is enough fast, also look at class Monitor with reflector for more details

苏佲洛 2024-11-14 09:47:56

锁将阻止其他线程执行锁块中包含的代码。线程必须等待,直到锁块内的线程完成并释放锁。这确实会对多线程环境中的性能产生负面影响。如果您确实需要这样做,您应该确保锁定块中的代码可以非常快速地处理。您应该尽量避免昂贵的活动,例如访问数据库等。

Locks will block other threads from executing the code contained in the lock block. The threads will have to wait until the thread inside the lock block has completed and the lock is released. This does have a negative impact on performance in a multithreaded environment. If you do need to do this you should make sure the code within the lock block can process very quickly. You should try to avoid expensive activities like accessing a database etc.

薄荷→糖丶微凉 2024-11-14 09:47:56

性能影响取决于您的锁定方式。您可以在这里找到一个很好的优化列表:http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/

基本上你应该尝试锁定尽可能少,因为它会让您的等待代码进入睡眠状态。如果您在锁中有一些繁重的计算或持久的代码(例如文件上传),则会导致巨大的性能损失。

The performance impact depends on the way you lock. You can find a good list of optimizations here: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/

Basically you should try to lock as little as possible, since it puts your waiting code to sleep. If you have some heavy calculations or long lasting code (e.g. file upload) in a lock it results in a huge performance loss.

掀纱窥君容 2024-11-14 09:47:56

lock 语句中的部分只能由一个线程执行,因此所有其他线程将无限期地等待持有锁的线程完成。这可能会导致所谓的死锁。

The part within the lock statement can only be executed by one thread, so all other threads will wait indefinitely for it the thread holding the lock to finish. This can result in a so-called deadlock.

尐偏执 2024-11-14 09:47:56

lock 语句被转换为对 监视器

lock 语句将无限期地等待锁定对象被释放。

The lock statement is translated to calls to the Enter and Exit methods of Monitor.

The lock statement will wait indefinitely for the locking object to be released.

无畏 2024-11-14 09:47:56

锁定实际上是隐藏的监视器类。

lock is actually hidden Monitor class.

剩余の解释 2024-11-14 09:47:56

根据 Microsoft 的 MSDN, lock 相当于:

object __lockObj = x;
bool __lockWasTaken = false;
try
{
    System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
    // Your code...
}
finally
{
    if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}

如果需要在运行时创建锁,可以使用开源的DynaLock 。您可以在运行时创建新锁,并使用上下文概念指定锁的边界。

DynaLock 是开源的,源代码可在 GitHub 获取

According to Microsoft's MSDN, the lock is equivalent to:

object __lockObj = x;
bool __lockWasTaken = false;
try
{
    System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
    // Your code...
}
finally
{
    if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}

If you need to create locks in runtime, you can use open source DynaLock. You can create new locks in run-time and specify boundaries to the locks with context concept.

DynaLock is open-source and source code is available at GitHub

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文