#多线程编程

互斥锁

常用来防止多个进程或线程同时访问相同的共享资源而导致的资源竞争。
互斥锁可以保证以下三点:

  • 原子性:保证当某个线程锁定了一个互斥锁,其他线程不可能在同时能锁定该互斥锁。
  • 唯一性:保证当某个线程已经锁定一个互斥锁时,在它解锁前,其他线程不可能锁定该互斥锁
  • 非繁忙等待:保证当某个线程已经锁定一个互斥锁时,第二个线程又试图去锁定这个互斥锁,则第二个线程将被挂起。

API

头文件 pthread.h

创建和销毁

互斥锁有静态和动态两种创建方式:

#静态方式使用 PTHREAD_MUTEX_INITIALIZER
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

#动态方式调用 pthread_mutex_init()函数
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
    参数pthread_mutex_t *restrict mutex:互斥锁
    参数pthread_mutexattr_t *restrict attr:互斥锁属性,一般填写NULL,且被忽略。
        如果mutex类型是 PTHREAD_MUTEX_NORMAL,不进行deadlock detection(死锁检测)。
        如果mutex类型是 PTHREAD_MUTEX_ERRORCHECK,那么将进行错误检查。
        如果mutex类型是 PTHREAD_MUTEX_RECURSIVE,mutex会有一个锁住次数(lock count)的概念。
        如果mutex类型是 PTHREAD_MUTEX_DEFAULT,企图递归的获取这个mutex的锁的结果是不确定的。

互斥锁销毁调用 pthread_mutex_destroy(),销毁已经被解锁的初始化互斥体是安全的。 尝试销毁锁定的互斥锁会导致未定义的行为,返回错误码EBUSY。

#销毁互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);

上锁和解锁

上锁有两种方式:

#pthread_mutex_lock()函数锁住由mutex指定的mutex 对象。如果mutex已经被锁住,调用这个函数的线程阻塞直到mutex可用为止。这跟函数返回的时候参数mutex指定的mutex对象变成锁住状态, 同时该函数的调用线程成为该mutex对象的拥有者。成功返回0,否则返回一个错误的提示码
int pthread_mutex_lock(pthread_mutex_t *mutex);

#pthread_mutex_trylock()调用在参数mutex指定的mutex对象当前被锁住的时候立即返回,除此之外,pthread_mutex_trylock()跟pthread_mutex_lock()功能完全一样。成功返回0,否则返回一个错误的提示码
int pthread_mutex_trylock(pthread_mutex_t *mutex);

解锁

#pthread_mutex_unlock()函数释放mutex对象的锁。如何被释放取决于该Mutex对象的类型属性。如果有多个线程为了获得该mutex锁阻塞,调用pthread_mutex_unlock()将是该mutex可用,一定的调度策略将被用来决定哪个线程可以获得该mutex锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);

条件变量

为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

API

头文件 pthread.h

创建和销毁

和互斥锁一样,有静态和动态两种创建方式,

#静态方式使用PTHREAD_COND_INITIALIZER常量, 
pthread_cond_t cond = PTHREAD_COND_INITIALIZER

#动态方式调用pthread_cond_init()函数,API定义如下:
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
参数pthread_cond_t *cond:条件变量
pthread_condattr_t *cond_attr:条件变量属性(由于在Linux Threads中没有实现,因此cond_attr值通常为NULL,且被忽略)

条件变量销毁调用pthread_cond_destroy(),只有在没有线程在该条件变量上等待的时候才能注销这个条件变量,否则返回EBUSY。因为Linux实现的条件变量没有分配什么资源,所以注销动作只包括检查是否有等待线程。

#销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond);

等待和唤醒

等待有两种方式:

#pthread_cond_timedwait()计时等待。如果在给定时刻前条件没有满足,则返回ETIMEOUT,结束等待.
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);

#pthread_cond_wait() 无条件等待,
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

#两种方式都需要配合互斥锁使用。同时,互斥锁必须是必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP)

唤醒也有两种方式。

#pthread_cond_signal() 唤醒一个等待该条件的线程,存在多个等待线程时按入队顺序唤醒其中一个;
int pthread_cond_signal(pthread_cond_t *cond);

#pthread_cond_broadcast() 唤醒所有等待线程
int pthread_cond_broadcast(pthread_cond_t *cond);

返回错误码

[EBUSY] The mutex could not be acquired because it was already locked. 
[EINVAL] mutex或者cond指向的对象未被初始化
[EAGAIN] mutex或者cond的count(数量)已经超过 递归索的最大值,
[EDEADLK] 当前线程已经获得该mutex或者cond
[EPERM] 当前线程不是该mutex或者cond的拥有者

你可能感兴趣的:(技术。,多线程,编程,线程)