线程安全问题:
当多个线程交叉执行并使用同一个数据时 并不会考虑数据数量 容易造成负数据(数据不一致 抢票系统可以很好的体现)
也就是说现在的操作大体为:某个线程访问某数据 进行到对该数据更改(使用)时 另一条线程也访问该数据 第一条线程挂起(等待)第二条线程对数据更改完后 第一条数据继续更改 并不会考虑数据实际情况
线程互斥:
多个线程访问临界资源时 只能当前线程执行完 才能执行下一条线程(原子性)。
这也就是临界资源和共享资源的区别:1.都能共享 2.临界不能迸发 共享可以
想要线程互斥实现 加把锁就可以了 访问时上锁 访问完解锁 就是以下操作
锁(互斥量):
初始化:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
销毁:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
这是单个锁的使用 用完销毁(必须)然后再创建 再销毁 太麻烦 有全局的 创建一次就好
全局:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
上锁:
int pthread_mutex_lock(pthread_mutex_t *mutex);
解锁:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
注意:
加锁和解锁之间就是临界区
一定要保证临界区粒度很小 就是代码量少(不准确理解)方便效率快
死锁:
产生条件:互斥条件 不可剥夺条件 请求与保持条件 环路等待条件
避免方法: 避免锁位释放的场景 加锁顺序一致 资源一次性分配
避免策略:
鸵鸟策略(出现概率低可以无视)
预防策略
避免策略
检测与解除死锁
重入函数:
可重入:
不使用全局变量 静态变量 malloc new
不返回静态或全局数据 只调用参数
不可重入:
调用malloc/free 有静态的数据结构
调用标准I/O库函数(标准I/O库使用不可重入的方式使用全局数据结构)
线程安全:
安全的线程:
不篡改全局变量 静态变量 原子性操作 线程切换没有二义性
不安全:
返回静态指针 函数每次被调用后意义不一样 不保护共享变量