线程的同步 互斥 条件变量 和 线程GDB调试

线程通信 – 互斥

临界资源
一次只允许一个任务(进程、线程)访问的共享资源

临界区
访问临界资源的代码

互斥机制
mutex互斥锁
任务访问临界资源前申请锁,访问完后释放锁

互斥锁初始化 – pthread_mutex_init

#include  
 int  pthread_mutex_init(pthread_mutex_t *mutex,
       const pthread_mutexattr_t *  attr);
 成功时返回0,失败时返回错误码
 mutex  指向要初始化的互斥锁对象
 attr  互斥锁属性,NULL表示缺省属性
man 函数出现 No manual entry for pthread_mutex_xxx解决办法 
	apt-get install manpages-posix-dev 

互斥锁销毁 pthread_mutex_destroy

int pthread_mutex_destroy(pthread_mutex_t *mutex)

申请锁 – pthread_mutex_lock

 #include  
 int  pthread_mutex_lock(pthread_mutex_t *mutex);
 int pthread_mutex_trylock(pthread_mutex_t *mutex)
 成功时返回0,失败时返回错误码
 mutex  指向要初始化的互斥锁对象
 pthread_mutex_lock 如果无法获得锁,任务阻塞
 pthread_mutex_trylock 如果无法获得锁,返回EBUSY而不是挂起等待

释放锁 – pthread_mutex_unlock

 #include  
 int  pthread_mutex_unlock(pthread_mutex_t *mutex);

 成功时返回0,失败时返回错误码
 mutex  指向要初始化的互斥锁对象
 执行完临界区要及时释放锁

读写锁

初始化一个读写锁   pthread_rwlock_init
读锁定读写锁        pthread_rwlock_rdlock
非阻塞读锁定  pthread_rwlock_tryrdlock
写锁定读写锁      pthread_rwlock_wrlock
非阻塞写锁定      pthread_rwlock_trywrlock
解锁读写锁         pthread_rwlock_unlock
释放读写锁         pthread_rwlock_destroy

死锁的避免

线程的同步 互斥 条件变量 和 线程GDB调试_第1张图片

条件变量

pthread_cond_wait(&m_cond,&m_mutex); 
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
           pthread_mutex_t *restrict mutex,
           const struct timespec *restrict abstime);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
条件变量
应用场景:生产者消费者问题,是线程同步的一种手段。
必要性:为了实现等待某个资源,让线程休眠。提高运行效率

int pthread_cond_wait(pthread_cond_t *restrict cond,
           pthread_mutex_t *restrict mutex);

int pthread_cond_timedwait(pthread_cond_t *restrict cond,
           pthread_mutex_t *restrict mutex,
           const struct timespec *restrict abstime);

int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);

使用步骤:
初始化:
静态初始化
pthread_cond_t   cond = PTHREAD_COND_INITIALIZER;      //初始化条件变量
pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;  //初始化互斥量
或使用动态初始化
pthread_cond_init(&cond);

生产资源线程:
pthread_mutex_lock(&mutex);
开始产生资源
pthread_cond_sigal(&cond);    //通知一个消费线程
或者
pthread_cond_broadcast(&cond); //广播通知多个消费线程
pthread_mutex_unlock(&mutex);

消费者线程:

pthread_mutex_lock(&mutex);
while (如果没有资源){   //防止惊群效应
	pthread_cond_wait(&cond, &mutex); 
}
有资源了,消费资源
pthread_mutex_unlock(&mutex);  

注意:
1 pthread_cond_wait(&cond, &mutex),在没有资源等待是是先unlock 休眠,等资源到了,再lock
所以pthread_cond_wait he pthread_mutex_lock 必须配对使用。

2  如果pthread_cond_signal或者pthread_cond_broadcast 早于 pthread_cond_wait ,则有可能会丢失信号。 
3 pthead_cond_broadcast 信号会被多个线程收到,这叫线程的惊群效应。所以需要加上判断条件while循环。

线程的GDB调试

显示线程
info thread 
切换线程
thread xxx

GDB为特定线程设置断点
break location thread id
GDB设置线程锁
set scheduler-locking on/off

线程的互斥和同步
临界资源概念:
不能同时访问的资源,比如写文件,只能由一个线程写,同时写会写乱。
比如外设打印机,打印的时候只能由一个程序使用。
外设基本上都是不能共享的资源。
生活中比如卫生间,同一时间只能由一个人使用。

必要性: 临界资源不可以共享

man手册找不到 pthread_mutex_xxxxxxx (提示No manual entry for pthread_mutex_xxx)的解决方法:
apt-get install manpages-posix-dev

互斥锁的创建和销毁
两种方法创建互斥锁,静态方式和动态方式
动态方式:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
其中mutexattr用于指定互斥锁属性,如果为NULL则使用缺省属性。
静态方式:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

锁的销毁:
int pthread_mutex_destroy(pthread_mutex_t *mutex)
在Linux中,互斥锁并不占用任何资源,因此LinuxThreads中的 pthread_mutex_destroy()除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作。

互斥锁的使用:
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)

vim 设置代码全文格式化:gg=G

读写锁
必要性:提高线程执行效率

特性:
写者:写者使用写锁,如果当前没有读者,也没有其他写者,写者立即获得写锁;否则写者将等待,直到没有读者和写者。
读者:读者使用读锁,如果当前没有写者,读者立即获得读锁;否则读者等待,直到没有写者。
注意:
同一时刻只有一个线程可以获得写锁,同一时刻可以有多个线程获得读锁。
读写锁出于写锁状态时,所有试图对读写锁加锁的线程,不管是读者试图加读锁,还是写者试图加写锁,都会被阻塞。
读写锁处于读锁状态时,有写者试图加写锁时,之后的其他线程的读锁请求会被阻塞,以避免写者长时间的不写锁

初始化一个读写锁 pthread_rwlock_init
读锁定读写锁 pthread_rwlock_rdlock
非阻塞读锁定   pthread_rwlock_tryrdlock
写锁定读写锁 pthread_rwlock_wrlock
非阻塞写锁定 pthread_rwlock_trywrlock
解锁读写锁 pthread_rwlock_unlock
释放读写锁 pthread_rwlock_destroy

死锁
概念:
避免方法:
1.锁越少越好,最好使用一把锁
2.调整好锁的顺序

你可能感兴趣的:(c语言)