Linux-线程同步和互斥

Linux线程基础—-线程同步与互斥

1.同步的概念

1.1 同步概念

所谓同步,即同时起步,协调一致.不同的对象,对”同步”的理解方式不同. 如: 设备同步是指两个设备之间规定一个共同的时间参考; 数据库同步,是指让两个或多个数据库保持一致,或者按需要部分保持一致; 文件同步,是指让两个或多个文件夹里的文件保持一致等等.而编程中,通信中所说的同步与生活中大家印象中的同步略有差异.”同”是指协同,协助,互助配合.主旨在协同步调,按预定顺序先后次序运行.

1.2 数据混乱的原因

1) 资源共享(独享资源不存在此问题)
2) 调度随机, 即意味着数据访问会出现竞争
3) 线程间缺乏必要的同步机制.

前面两点不能改变,欲提高效率,传递数据资源必须共享.只要共享资源就一定会出现竞争.只要存在竞争关系,数据就很容易出现混乱。所以只能从第三点着手解决。使多个线程在访问共享资源的时候,出现互斥。

3.线程同步

是一个宏观概念,在微观上包含线程的相互排斥和线程先后执行的约束问题.
同步即协同步调,按预定的先后次序运行.
线程同步指一个线程发出某一功能调用时, 在没有得到结果前,该调用不返回. 同时其他线程为保证数据一致性,不能调用该功能. 如: A任务的运行依赖于B任务产生的数据.
目的: 是为了避免数据混乱,解决与时间有关的错误.实际上,不仅线程间需要同步,进程间,信号间等都需要同步. 因此, 所有"多个控制流,共同操作一个共享资源"的情况,都需要同步.

解决同步办法: 条件变量, 线程信号量

2.线程同步手段

线程互斥

线程执行的相互排斥.
散步在不同任务之间的若干程序片断,当某个任务运行其中一个程序片段时,其它任务就不能运行它们之中的任一程序片段,只能等到该任务运行完这个程序片段后才可以运行。最基本的场景就是:一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。
解决互斥方式: 互斥锁,读写锁,线程信号量

互斥锁创建和销毁

#include <pthread.h>
//创建快速互斥锁.
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
//创建递归互斥锁.
pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
//创建检错互斥锁.
pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

//创建并初始化一个互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
//功能:上锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
//功能:尝试上锁,拿不到锁返回出错信息
int pthread_mutex_trylock(pthread_mutex_t *mutex);
//功能:释放锁
int pthread_mutex_unlock(pthread_mutex_t *mutex); ///成功返回0,出错返回出错码

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

参数: 
mutex: 互斥锁.
mutexattr: 互斥锁创建方式.

互斥锁属性创建和销毁

#include <pthread.h>
int pthread_mutexattr_init(pthread_mutexattr_t *attr);    
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);

互斥锁类型操纵
[mutex_lock_type.c]
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind);
attr: 互斥锁属性;
type: 互斥锁类型: 
    1)标准互斥锁: PTHREAD_MUTEX_NORMAL, 第一次上锁成功,第二次上锁会阻塞.
    2)递归互斥锁: PTHREAD_MUTEX_RECURSIVE, 第一次上锁成功,第二次上锁还是成功,内部计数.
    3)检错互斥锁: PTHREAD_MUTEX_ERRORCHECK, 第一次上锁成功,第二次上锁出错.
    4)默认互斥锁: PTHREAD_MUTEX_DEFAULT, 同标准互斥锁.

互斥锁进程共享属性操作
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restric attr, int *restrict pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);
返回: 成功返回0, 出错返回错误编号.
线程共享属性:
    PTHREAD_PROCESS_PRIVATE, 默认情况, 锁只能用于一个进程内部的两个线程进行互斥.
    PTHREAD_PROCESS_SHARED, 锁可以用于两个不同进程中的线程进行互斥.
缺点: 线程使用互斥锁缺乏读并发性.

线程互斥 - 读写锁

当读操作较多,写操作较少时,可使用读写锁提高线程读并发性.
(1) 创建和销毁
#include <pthread.h> 
int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *restrict attr);   
int pthread_rwlock_destroy(pthrad_rwlock_t *rwlock);
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

(2) 读写锁加锁和解锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); //加读锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); //写加锁
int pthread_rwlock_unlock(phtread_rwlock_t *rwlock); //释放锁
成功返回0, 失败返回错误编号.