2010-07-15 85 views
1

现在我试着学习多线程和mutext。但我不明白。例如,我添加项目列表在anotyher线程然后主程序:解释它是如何工作的互斥体

GMutext* lock; 
g_mutex_lock (lock); 
g_list_prepend(list, "Some data"); 
g_mutex_unlock (lock); 

在这种情况下,列表中会发生什么?添加元素的列表,以及直到g_mutex_unlock才从主线程访问?或者我错了解它?

谢谢。

谢谢。

回答

4

当互斥锁被锁定时,任何想要锁定它的其他线程都会阻塞,直到当前持有该锁的线程解锁互斥锁。这与列表对象无关 - 如果其他线程不尝试锁定相同的互斥锁,则可尝试对列表执行任何操作,并发访问可能会导致列表损坏。

所以锁定mutext是一个惯例。调用者必须遵守约定 - 尝试在访问保护的数据对象之前获取互斥锁。数据对象和互斥体之间的映射取决于开发人员。

+0

谢谢你的回复。 所以我理解正确。目前没有人可以访问该列表? – 0xAX 2010-07-15 06:04:02

+1

只有那些试图阻止锁定的人才没有并发访问权限。 – sharptooth 2010-07-15 06:06:32

+1

@sterh:没有人*在触摸列表之前遵循抓取互斥锁的协议*可以访问列表。如果你忘记首先获取互斥锁,那么当另一个线程拥有它时,没有什么能够阻止你操纵列表,因为他们真正拥有的是互斥锁。 – cHao 2010-07-15 06:06:44

3

不,任何人访问列表外部互斥量仍然可以看到更改。但是你不应该那样做(通常,无论如何)。关键是允许变化有效地变成原子 - 你将锁定你需要访问共享状态的互斥体无处不在。这可以有效地串行化线程间的访问,因此每个线程都可以进行更改(或读取其数据),因为知道没有其他任何东西正在搞乱列表。但它是合作的 - 如果你在访问列表时忘记锁定互斥锁,就会冒数据竞争的风险。

1

互斥意味着:相互排斥。这意味着,互斥对象只能由一个用户同时访问。有不同的处理方式,一个忙着等待,还有信号量。有些CPU像指令一样具有互斥体,测试并设置为原子操作。

2

互斥锁和列表是两个独立的对象。没有任何东西阻止你访问互斥体外的列表,因此不能保证互斥(因此名称互斥)。

你会经常看到这样的代码:

GMutext* lock; 
GList* list 

void addData(string data) { 
    g_mutex_lock (lock); 
    g_list_prepend(list, data); 
    g_mutex_unlock (lock); 
} 

string getData() { 
    g_mutex_lock (lock); 
    GList* data = g_list_first (list); 
    g_list_remove(list, data); 
    g_mutex_unlock (lock); 
    return data; 
} 

这确保了列表总是安全地访问。如果另一种方法直接访问列表而不使用相同的互斥体,则不能保证列表可以处于什么状态(例如,检索/添加什么数据)。