Skip to main content
 首页 » 编程设计

c#之线程和锁定资源

2024年01月22日30freeliver54

我希望得到一些帮助来理解一个概念。对于术语的不当使用,我深表歉意。我是 OOP 的新手,所以请多多包涵。

这里有一些伪代码来显示这个问题:

public MyClass 
{ 
    myClass singleton; //singleton object of myClass (only one instance created) 
    myCollection; //list or array 
    private object _lock; 
 
    public myFunction() 
    { 
        lock(myCollection) //or do I use lock(_lock)? 
        { 
            try 
            { 
                //modifies my collection 
            } 
            catch 
            { 
                //exception 
            } 
        } 
    } 
 
    public secondFunction() 
    { 
        //modify my collection 
    } 
 
    public getMyCollection() 
    { 
        return myCollection; 
    } 
 
} 

现在假设我们有两个对象在来自 classA 和 classB 的不同线程上(我将这些对象称为 objA 和 objB),它们正在尝试访问 MyClass。

1) 如果 objA 正在使用 myFunction,我明白 objB 将无法同时使用 myFunction 由于锁定。

但是objB可以使用secondFunction()吗? 还是 myFunction() 上的锁会保护 myCollection 在锁被释放之前不被修改?

如果上述问题为真:如果objA正在使用myFunction(),而objB正在尝试使用secondFunction(),那么objB线程是否会等待直到锁被释放?

2) 什么是更好的约定? 锁(_锁) 或者 锁(我的收藏)

3) 如果我在 myfunction() 中使用 lock(_lock),它是否仍会保护 myCollection 不在 secondFunction() 中被访问?

感谢您的时间和耐心。

请您参考如下方法:

If objA is using myFunction, I understand that objB won't be able to use myFunction at the same time due to the lock.

需要说明的是:这里的 objA 和 objB 是“在线程 A 上调用”和“在线程 B 上调用”的简写。

你的说法基本正确;我们可以更明确地说,如果线程 A 获取锁,那么线程 B 获取锁的尝试将阻塞,直到线程 A 释放锁。

另请注意,不能保证锁是公平的。如果线程 C 在线程 B 之后尝试获取锁,则无法保证线程 B 在线程 A 释放锁时获取锁。线程 C 可以先走。

这样想。你有一片沙漠。沙漠中央是一个浴缸。没有墙。浴缸旁边有一扇门。门有锁。规则是:如果你想用浴缸而且门没有锁,锁门,洗澡,开门。如果您想使用浴缸并且门被锁上了,请等到它被解锁。如果有多个人在等待,则通过某种未指定的机制选择一个人赢得比赛。

However, can objB use secondFunction()?

当然。这将违反规定,无论门是否锁上都跳进浴缸。请记住,没有墙。

Or does the lock on myFunction() protect myCollection from being modified until the lock is released?

完全没有。 除了在每个可以修改的地方放置相同锁之外,没有任何东西可以阻止 myCollection 被修改。也就是要求每个人想用浴缸都要在门口等。

If objA is using myFunction(), and objB is trying to use secondFunction(), will the objB thread wait until the lock is released?

没有; secondFunction 没有锁。

再次回到基础。锁可以由线程获取,也可以由获取它的线程释放。同一个线程可以多次获取锁而不释放它。一旦所有的获取都有相应的释放,锁就可以被任何其他线程自由获取。

为了您现在的目的,就是这样。锁非常非常简单。你获得它们,如果你不能获得它们,你会一直阻塞直到你可以,一旦你获得了锁,你需要在不久之后释放它,让其他人可以轮到。

使用锁的方法要复杂得多,但请从基础开始。

What is the better convention? lock(_lock) or lock(myCollection)

始终锁定专用对象,该对象是私有(private)的,除了锁定之外别无他用。如果您偏离此最佳实践,有很多种方法可能会导致严重错误。

尤其永远不要锁定 Type、string 或 this。

If I use lock(_lock), in myfunction(), will it still protect myCollection from being accessed in secondFunction()?

没有。再次回到锁的定义。锁定语句尝试获取锁。这就是它所做的全部。如果你在其他地方有一些其他功能在需要时没有获得锁,那么,这就是一个错误。如果这听起来像是一个容易编写的错误,确实是。

多线程 super 难,如果您不小心,很容易导致很多人同时陷入困境。这不像听起来那么有趣,因为他们都没有就水是否应该流水达成一致,也许他们中的一些人在里面有人的时候试图清洁那个浴缸,这是一团糟,让你的过程崩溃,丢失用户数据。