linux 同步

互斥锁用户保护“临界区域”(critical region),以保证任何时刻只有一个线程在执行其中的代码(假设互斥锁由多个线程共享),或者任何时刻只有一个进程在执行其中的代码(假设互斥锁有多个进程共享)。

Posix互斥锁被声明为具有pthread_mutex_t数据类型的变量。如果互斥锁变量是静态分配的,那么我们可以把它初始化成常值PTHREAD_MUTEX_INITIALIZER,例如

    static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

如果互斥锁是动态分配的(例如通过调用malloc),或者分配在共享内存区中,那么我们必须在运行之时通过调用pthread_mutex_init函数来初始化它。

互斥锁是协作性(cooperative)锁。这就是说,如果共享数据是一个链表(举个例子),那么操纵该链表的所有线程都必须在实际操纵前获取该互斥锁。不过也没有办法防止某个线程不首先获取该互斥锁就操纵该链表。

互斥锁用于上锁(locking)而不能用于等待(waiting)。因为它是busy-waiting。就是说当没有可用的锁时,就一直忙等待并不停的进行锁请求,直到得到这个锁为止。这个过程中cpu始终处于忙状态,不能做别的任务。只是一种对CPU的浪费。

 

互斥锁用于上锁,条件变量则用于等待。这两种不同类型的同步都是需要的。每个条件变量总是有一个“互斥锁”与之关联。我们调用pthread_cond_wait等待某个条件为真时,还会指定其条件变量的地址和所关联的互斥锁的地址 int pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr)。

 

互斥锁把试图进入我们称之为临界区的所有其它线程都阻塞住。读写锁(read-write lock),其分配规则如下:

一:只要没有线程持有某个给定的读写锁用于写,那么任意数目的线程可以持有该读写锁用于读。

二:仅当没有线程持有某个给定的读写锁用于读或用于写时,才能分配该读写锁用于写。

这种访问方式也成为共享-独占上锁。

 

读写锁作为pthread_rwlock_t数据类型的变量在内存中分配的。当读写锁在单个进程内的多个线程间共享时(默认情况),这些变量可以在那个进程内;当读写锁是在共享某个内存区的进程间共享时,这些变量应该在该共享内存区中。记录上锁的Posix接口是fcntl函数。“记录上锁”也称为“劝告性上锁”,这含义是内核维护着已由各个进程上锁的所有文件的正确信息,但是它不能防止一个进程写已由另一个进程读锁定的某个文件(只要有读写这个文件的权限)。其实“记录上锁”更好的称谓是“范围上锁(range locking)”。

 

为对某个特定文件执行强制性上锁,应满足:

一:组成员执行位必须关闭。

二:SGID位必须打开。

 

Posix.1保证,如果以O_CREATE(若文件不存在则创建它)和O_EXCL(独占打开)标志调用open函数,那么一旦该文件已经存在,则调用失败。这样该文件的存在本身代表锁。这种方法通常存在于fcntl上锁尚未广泛得以实现之前编写的程序中。

 

信号量(semaphore)是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语。信号量分“二值信号量”和“计数信号量”。

信号量mutex是sleep-waiting。 就是说当没有获得mutex时,会有上下文切换,将自己、加到忙等待队列中,直到另外一个线程释放mutex并唤醒它,而这时CPU是空闲的,可以调度别的任务处理。

你可能感兴趣的:(linux 同步)