互斥锁应该存储在main还是对象中?

Kai*_*aiJ 2 c mutex thread-safety

以C中的对象为例:

/* object.h */

typedef struct Object Object;

Object* createObject();
void freeObject(Object* object);

int getObjectNumber(Object* object);
void incrementObjectNumber(Object* object);
Run Code Online (Sandbox Code Playgroud)

这是一种非常简单的不透明类型,它存储一个数字并可以递增。

为了使我的代码线程安全,我有两个选择。第一种是在对象中存储互斥量:

void
func(Object* object)
{
    incrementObject(object);
}

int
main()
{
    Object* object = createObject();

    Thread thread1 = startThread(func, object);
    Thread thread2 = startThread(func, object);

    waitThread(thread1);
    waitThread(thread2);

    freeObject(object);
}
Run Code Online (Sandbox Code Playgroud)

第二种是将互斥锁存储在main中:

void
func(Object* object, Mutex mutex)
{
    lockMutex(mutex);
    incrementObject(object);
    unlockMutex(mutex);
}

int
main()
{
    Object* object = createObject();

    Mutex mutex;

    Thread thread1 = startThread(func, object, mutex);
    Thread thread2 = startThread(func, object, mutex);

    waitThread(thread1);
    waitThread(thread2);

    freeObject(object);
}
Run Code Online (Sandbox Code Playgroud)

如果只会有一个对象,哪种方法更好?

Lun*_*din 5

无论有一个对象还是多个对象,将互斥体与不透明的对象一起存储都是一个好主意。首先,互斥锁及其保护的数据属于同一类。而且,线程安全需要由您的“ ADT”来处理,而不是由调用者来处理。对对象的访问应仅通过设置器/获取器进行,后者将在内部处理线程安全性。在这种情况下incrementObject

这样,您可以声明您的整个库是线程安全的,它会照顾自己而不是将责任转嫁给其他人。您的第一个示例的API更加简洁,而第二个示例则要求调用者将一个互斥锁拖到其用户定义的回调中,这不是一个干净的解决方案。