简体   繁体   English

互斥锁在单独的类上

[英]Mutex lock on separate classes

What is the correct use of a Mutex? Mutex的正确用法是什么? How do I know what it is protecting? 我怎么知道它在保护什么? Does it stop all threads from running for the locked period? 是否会在锁定期间停止所有线程的运行?

For example I have a singleton that contains a list of objects. 例如,我有一个包含对象列表的单例。

class Foo
{
    // Pretend this is a singleton.
    std::list<Object>* GetObjects() { return &objects; }
    void Reset() { for ( auto iter = objects.begin(); iter != objects.end(); ++iter ) { delete *iter; } }
    std::list<Object> objects;
};

In a separate class I have a update method. 在一个单独的类中,我有一个update方法。 This is run in a seperate thread. 这在单独的线程中运行。

class Bar
{
    void Update()
    {
        std::list<Object>* objects Foo.GetObjects(); 
        for(auto iter = objects.begin(); iter != objects .end(); ++iter )
            iter->SetTransform(50,50,50);
    }
};

My Problem is that I want to call Reset() on Foo, and delete all the objects. 我的问题是我想在Foo上调用Reset()并删除所有对象。 But my Bar class is updating all these objects. 但是我的Bar类正在更新所有这些对象。 So if it is in the middle of a update method it may be trying to modify a object that has been deleted. 因此,如果它处于更新方法的中间,则可能正在尝试修改已删除的对象。

How do I prevent this? 我该如何预防?

Can I just create a Mutex in reset function and lock it before deleting and unlock it after? 我可以在重置功能中创建互斥锁并在删除之前将其锁定,然后再解锁吗? Something like this: 像这样:

 void Reset()
 {
     Mutex mutex; mutex.Lock()
     for ( auto iter = objects.begin(); iter != objects.end(); ++iter )
         delete *iter;
     mutex.Unlock();
}

Does this let the other class know these resources are locked? 这是否会让其他班级知道这些资源已锁定? I am not sure how the mutex knows what information to protect. 我不确定互斥锁如何知道要保护的信息。 How does it know that it needs to lock the list in the singleton class. 它如何知道它需要将列表锁定在单例类中。

Btw this is all pseudo code so there is syntax errors and missing information. 顺便说一句,这都是伪代码,因此存在语法错误和信息丢失。

In simple terms, a mutex is a locking mechanism. 简单来说,互斥锁是一种锁定机制。

say, you have a resource, in your case list<object> objects; 例如,您有一个资源,就您的情况而言, list<object> objects; Now , If multiple threads end up operating on this list concurrently, then, the outcome of these operations could be unexpected. 现在,如果多个线程最终同时在此列表上运行,那么这些操作的结果可能是意外的。

so, basically mutex gives us a mechanism that ensures that only one thread operated on the protected resource one at a time. 因此,互斥锁基本上为我们提供了一种机制,可确保一次仅在受保护资源上运行一个线程。

Implementation: 执行:

In Linux kernel, a thread is modeled by a task_struct object.And mutex implementation is as follows: 在Linux内核中,线程是由task_struct对象建模的,并且互斥量实现如下:

struct mutex {
  /* 1: unlocked, 0: locked, negative: locked, possible waiters */
  atomic_t                count;
  spinlock_t              wait_lock;
  struct list_head        wait_list;
 #if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
  struct task_struct      *owner;
 #endif
}

So, first thread to try to lock mutex becomes the owner and everyone else is added to wait_list of that mutex. 因此,尝试锁定互斥锁的第一个线程将成为owner ,其他所有人都将添加到该互斥锁的wait_list中。

Once the owner releases it, the next task from the wait_list gets the next chance. 所有者释放它之后, wait_list的下一个任务将获得下一次机会。

Note that 注意

in case of mutex, whoever locks it has to unlock it, 如果是互斥锁,则锁定它的人必须将其解锁,

else everyone else will be locked forever, also known as dreadlock . 否则其他所有人将被永远锁定,也称为dreadlock

What is the correct use of a Mutex? Mutex的正确用法是什么?

To synchronize access to a shared resource. 同步对共享资源的访问。

How do I know what it is protecting? 我怎么知道它在保护什么?

By reading the code. 通过阅读代码。 Whatever is accessed when the lock is acquired is what is being protected. 获取锁时访问的是受保护的东西。

Does it stop all threads from running for the locked period? 是否会在锁定期间停止所有线程的运行?

No. Only people who wait on the Mutex are "stopped". 不。只有等待Mutex的人才能“停下来”。 A thread will wait when you call Lock() if some other thread already has the lock. 如果某个其他线程已经拥有该锁,则该线程将在您调用Lock()时等待。 It will wait until whoever has the lock calls Unlock() . 它将等待,直到拥有锁的人调用Unlock() If nobody has the lock then the thread calling Lock() acquires it and does not wait. 如果没有人拥有该锁,则调用Lock()的线程将获取它并且不等待。 Multiple threads may be waiting if you have a lock and who gets it when it is unlocked is not necessarily defined. 如果您拥有锁,则不一定要定义多个线程,并且解锁时谁会得到锁。 Refer to the documentation for your particular framework. 请参阅您特定框架的文档。

How do I prevent this? 我该如何预防? Can I just create a Mutex in reset function and lock it before deleting and unlock it after? 我可以在重置功能中创建互斥锁并在删除之前将其锁定,然后再解锁吗?

You can prevent simultaneous access to a shared resource by multiple threads if you acquire and release the lock around access to that shared resource. 如果获取并释放了对该共享资源的访问锁,则可以防止多个线程同时访问共享资源。 So, yes, you can lock and unlock around your reset code, but you need to do it in all the places that access your shared resource. 因此,是的,您可以在重置代码周围进行锁定和解锁,但是您需要在访问共享资源的所有位置进行重置。

In this case objects is your shared resource. 在这种情况下, objects是您的共享资源。 If you acquire the lock in the place you delete the contents of objects , you must also acquire the lock in places where you're using it. 如果您在删除objects内容的位置获得了锁,则还必须在使用它的位置获得该锁。 Since you give out a reference via GetObjects() you would also need to have callers of that realize access needs to be synchronized via this mutex. 由于您通过GetObjects()给出了一个引用,因此您还需要使该调用者意识到访问需要通过此互斥锁进行同步。

An alternative scheme would be to get rid of GetObjects() and have other methods, for example Object *get(int index) , that get / set / manipulate the data inside the lock and never actually give out a raw reference to objects . 一种替代方案是摆脱GetObjects()并拥有其他方法,例如Object *get(int index) ,该方法获取/设置/操作锁中的数据,而从不实际提供对objects的原始引用。

Does this let the other class know these resources are locked? 这是否会让其他班级知道这些资源已锁定? I am not sure how the mutex knows what information to protect. 我不确定互斥锁如何知道要保护的信息。

No. The Mutex doesn't know anything. 不,互斥体什么都不知道。 You must impose the proper semantics on the code, either by documenting it for callers or thunking all access to the shared resource through an object that knows to acquire the Mutex. 您必须在代码上施加适当的语义,或者通过为调用者提供文档记录,或者通过知道要获取Mutex的对象来对共享资源进行所有访问。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM