线程同步与互斥量

来源:互联网 发布:xboxonex 知乎 编辑:程序博客网 时间:2024/06/06 08:38
线程同步:
当多个线程共享相同的内存时,需要确保每个线程看到一致的数据视图。如果每个线程使用的变量都是其他线程不会读取和修改的,那么就不存在一致性问题。同样,如果变量是只读的,多个线程同时读取该变量也不会有一致性的问题。但是,当一个线程可以修改的变量,其他线程也可以读取和修改的时候,我们就需要对这些线程进行同步,确保它们在访问变量的存储内容时不会访问到无效的值。

为了解决这个问题,线程不得不使用锁,同一时间只允许一个线程访问该变量。

两个或多个线程在同一时间修改同一变量,也需要进行同步。考虑变量增量操作的情况,增量操作通常分解为3个步骤:
>>>1. 从内存单元读入寄存器
>>>2. 在寄存器中对变量进行增量操作
>>>3. 把新的值写回内存单元

互斥量:
可以使用pthread的互斥接口来保护数据,确保同一时间只有一个线程访问数据。
互斥量(mutex)从本质上述是一把锁,在访问共享资源前对互斥量进行设置(加锁),在访问完成后释放(解锁)互斥量。对互斥量进行加锁以后,任何其他试图再次对互斥量加锁的线程都会被阻塞直到当前线程释放该互斥锁。如果释放互斥量时有一个以上的线程阻塞,那么所有的该锁上的阻塞线程都会变成可运行状态,第一个变为运行的线程就可以对互斥量加锁,其他线程就会看到互斥量依然是锁着的,只能回去再次等待它重新变为可用。在这种方式下,每次只有一个线程可以向前执行。

只有将所有线程都设计成遵守相同数据访问规则的,互斥机制才能正常工作。操作系统并不会为我们做数据访问的串行化。如果允许其中的某个线程在没有得到锁的情况下也可以访问共享资源,那么即使其他的线程在使用共享资源前都申请锁,那么也还是会出现不一致的问题。

互斥变量使用pthread_mutex_t数据类型表示的。在使用互斥变量以前,必须首先对它进行初始化,可以把它设置为常量PTHREAD_MUTEX_INITIALIZER(只适用于静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化。如果动态分配互斥量(例如,通过调用malloc函数),在释放内存前需要调用thread_mutex_destroy.

#include <pthread.h>int pthread_mutex_init(pthread_mutex_t *restrict mutex,                        const pthread_mutexattr_t *restrict attr);int pthread_mutex_destroy(pthread_mutex_t *mutex);                            //两个函数的返回值:若成功,返回0;否则,返回错误编号;//Hip: 互斥量的属性本章博客将不说明

要用默认的属性初始化互斥量,只需把attr设为NULL。

对互斥量进行加锁,需要调用pthread_mutex_lock. 如果互斥量已经上锁,调用线程将阻塞直到互斥量被解锁。对互斥量解锁,需要调用pthread_mutex_unlock.

#include <pthread.h>int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_trylock(pthread_mutex_t *mutex);int thread_mutex_unlock(pthread_mutex_t *mutex);                           //所有函数的返回值:若成功,返回0;否则,返回错误编号;

如果线程不希望被阻塞,它可以使用thread_mutex_trylock尝试对互斥量进行加锁。如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么pthread_mutex_trylock将锁住互斥量,不会出现阻塞直接返回0,否则othread_mutex_trylock就会失败,不能锁住互斥量,返回 EBUSY.

0 0
原创粉丝点击