Linux网络编程面试--多线程同步
主要有以下几种同步方式:
1.线数据分离
为每个线程准备一套数据,线程之间彼此独立,没有读写竞争。
2.环形缓冲区
如果是一个数据队列,两个线程分别读写,则可以用环形缓冲区来同步。维护两个变量,写偏移量和读偏移量
(1)如果队列长度为N,读写偏移量为N-1,则下一次偏移量为0,如此递增----环形
(2)如果读偏移P大于写偏移Q则可以读取P-->N-1-->Q之间的数据,因为Q-->N-1还未写新数据。
(3)如果读偏移P小于写偏移Q则可以读取P-->Q之间的数据。
环形缓冲区主要用于:
(1)顺序队列缓冲更新
(2)数据空间不释放的情况
(3)读写不需要锁的情况
3.互斥锁
//创建锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr);
//释放锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
//锁住资源
int pthread_mutex_lock(pthread_mutex_t *mutex);
//释放锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);
互斥锁主要用于对资源的独占情况,属于阻塞式独享,只允许一个线程同时访问资源。
4.信号量
//初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);//删除信号量
int sem_destroy(sem_t *sem);//等待一个信号量可用
int sem_wait(sem_t *sem);
//释放一个信号量
int sem_post(sem_t *sem);
信号量主要用于需要控制资源的访问数量的情况,允许多个线程同时进入临界区。
5.临界区
//初始化临界区
InitializeCriticalSection
//释放临界区
DeleteCriticalSection
//进入临界区
EnterCriticalSection
//离开临界区
LeaveCriticalSection
临界区与互斥锁的区别:
(1)临界区是用户态-速度快,互斥锁是内核态-速度慢。
(2)临界区主要用于数据和代码块保护,互斥锁主要用于数据独享。
(3)临界区必须是拥有临界区的对象的单元中才能访问,互斥锁则可以在其它线程或进程中访问。
6.事件
//创建一个信号量
CreateEvent
//打开一个事件
OpenEvent
//回置事件
SetEven
//等待一个事件
WaitForSingleObject
//等待多个事件
WaitForMultipleObjects
事件对象通过通知操作的方式来保持线程的同步