什么是线程同步?
在多线程编程时,如果变量是只读的,多个线程读取变量时并不会有一致性问题,但是,当一个线程可以修改的变量,其他的线程也可以读或者修改的时候,我们就需要对线程就行同步,确保线程看到的数据必须一致,确保访问变量时不会出现无效的值
Linux对线程提供了几种基本的同步机制
一. 互斥量
互斥量从本质上来说是一把锁,多线程编程时,在访问共享资源时对互斥量进行设置(即加锁),访问完成之后,再释放(解锁)互斥量.
对互斥量进行加锁之后,任何试图再次对互斥量进行加锁的线程都会被阻塞直到当前线程释放该互斥锁.
如果释放时有一个以上的线程阻塞,那么该锁上的阻塞线程都会变成可运行状态,第一个变为运行的线程就可以对互斥量进行加锁,其他线程看到互斥锁依然是锁着的时候就只能回去再次重新阻塞等待.
互斥变量使用pthread_mutex_t数据类型表示的,使用互斥变量之前,需要对它进行初始化
·可以把互斥量设置为PTHREAD_MUTEX_INITIALIZER(使用于静态分配的互斥量)
·可以调用pthread_mutex_init函数进行初始化,如果动态分配了互斥量,在释放内存前需要调用pthread_mutex_destroy函数
销毁互斥量时需要注意:
·使用PTHREAD_MUTEX_INITIALIZER初始化的互斥量不需要销毁
·不要销毁一个已经加锁了的互斥量
·已经销毁的互斥量,要确保后面不会再有线程尝试加锁
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_lock函数
·对互斥量进行解锁需要调用pthread_mutex_unlock函数
·如果线程不希望加锁时被阻塞,可以使用pthread_mutex_trylock函数尝试对互斥量进行加锁.如果调用时互斥量处于未锁状态,则这个函数会锁住互斥量,不会阻塞等待,否则pthread_mutex_trylock就会失败,不能锁住互斥量,返回EBUSY
举个栗子:
在主函数中,对全局变量互斥量mutex进行初始化,然后再创建四个线程,然后线程等待,最后再末尾调用pthread_mutex_destroy函数
四个线程使用同一个线程处理函数,每个线程都是一个循环,循环内部对操作进行加锁和解锁