欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > 3.16-线程同步

3.16-线程同步

2025/3/17 12:18:20 来源:https://blog.csdn.net/2401_87984258/article/details/146302025  浏览:    关键词:3.16-线程同步

线程同步

  • 同步:即协同步调,按预定的先后次序访问共享数据。
  • 数据同步:指一个线程发出某一功能调用时,没有得到结果前,该调用不返回。同时,其他线程为保证数据一致性,不调用该功能。

数据混乱的原因

  1. 资源共享
  2. 调度随机
  3. 线程之间缺乏必要的同步机制
  • 锁的属性:
    • 系统提供给用户的所有锁全部为”建议锁“,不具备强制性。
    • 如果访问共享数据的线程不拿锁,直接访问共享数据,能访问成功但是数据就会有出现混乱的风险。——拿锁与否完全取决于程序的编写。

互斥量(互斥锁)

pthread_mutex_t mutex;创建互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t  *mu‐
texattr); // 初始化互斥锁int pthread_mutex_lock(pthread_mutex_t *mutex); // 加锁,如果锁被占用,阻塞
int pthread_mutex_trylock(pthread_mutex_t *mutex); // 尝试加锁,不阻塞int pthread_mutex_unlock(pthread_mutex_t *mutex); // 解锁,唤醒阻塞在此锁上的进程int pthread_mutex_destroy(pthread_mutex_t *mutex); // 销毁互斥锁

注意事项:

  1. 锁的粒度越小越好(访问共享数据前,加锁,访问共享数据结束后,立即解锁)。
  2. 互斥锁,本质:结构体。我们可以把它当成整数看待,初始值为 1
  3. 加锁:-- 操作。失败:阻塞线程
  4. 解锁:++ 操作
  5. try:尝试加锁。成功:–,失败,设置错误号。
  • 初始化互斥量:
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; // 静态初始化
pthread_mutex_init(&mut, NULL; // 动态初始化 

死锁

  • 死锁不是锁,是一种错误使用锁的状态。
  • 常见死锁种类:
    1. 对一把锁反复 lock。
    2. 两个线程各自持有一把锁,请求另一把锁。

读写锁

  1. 锁只有一把,可以指定为”读模式“和”写模式“。
  2. 读共享,写独占。
  3. 写锁优先级高。
  • 相较于互斥锁而言,读写锁适合对数据结构读的操作次数远高于写的次数的场景。

操作函数

pthread_rwlock_t rwlock; // 创建读写锁对象int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);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_trywrlock(pthread_rwlock_t *rwlock);
  • restrict 关键字:
    • 用来修饰指针标量。被该关键字修饰的指针变量指向的内存操作,只能由本指针完成。

条件变量

  • 条件变量不是锁,通常配合互斥锁使用,也能造成线程阻塞

操作函数

pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // 静态初始化int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); // 动态int pthread_cond_signal(pthread_cond_t *cond); // 唤醒阻塞在条件变量上的线程int pthread_cond_broadcast(pthread_cond_t *cond); // 唤醒阻塞在条件变量上的线程int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); // 等待条件满足
作用:1. 阻塞等待条件满足。2. 解锁已经加锁成功的互斥量。——1. 2. 为一个原子操作,不可再分。...等待...3. 当条件满足,函数返回时,重新加锁
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const
struct timespec *abstime); // 超时退出int pthread_cond_destroy(pthread_cond_t *cond); // 销毁条件变量

信号量

  • 信号量与信号无关
  • 信号量相当于初始值为 N 的互斥量,可以表示同时访问共享数据的线程数。

操作函数

sem_t int sem_init(sem_t *sem, int pshared, unsigned int value);
// 动态初始化,没有静态20:用于线程间同步非 0:用于进程间同步
参 3:信号量的初值 N
返回值:成功:0  失败:-1,errno
int sem_destroy(sem_t *sem);int sem_trywait(sem_t *sem);int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);int sem_post(sem_t *sem);
// 一次调用做一次 ++ 操作。当信号为 N 的时候再次 ++ 会阻塞。
int sem_wait(sem_t *sem);
// 一次调用做一次 -- 操作。当信号为 0 的时候再次 -- 会阻塞。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词