linux多线程编程2-线程同步

1、线程同步的概念:这里说的同步并非时同时的概念,而是指协同、协助、互相配合,即按照一定的次序完成需要的动作,使程序正常运行。所谓的线程同步,指的是一个线程某个功能调用时,没有得到结果之前,该调用不返回,同时其他线程为保证数据一致性,不能调用该功能。

2、互斥量:两个线程访问同一块资源,如果不协调顺序,容易造成数据混乱,这时候,就需要加上一把锁。例如,只有一个厕所,a先进去,为了防止下一个人进来,他就先把厕所门给锁住,等自己拉完过后再将门打开,这时候即释放了锁,下一个人就可以进去,再上锁,以此重复。

  mutex

  锁的初始化:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

        pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

        其中 restrict 代表强制使用mutex这个结构进行初始化,初始化锁有两种方式,一种是定义一个pthread_mutex_t 变量,之后调用init函数进行初始化,属性一般传NULL; 另一种就是通过宏进行初始化,即通过pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER来初始化一个全局锁。

  摧毁锁: int pthread_mutex_destroy(pthread_mutex_t *mutex);

  加锁:int pthread_mutex_lock(pthread_mutex_t *mutex);

     如果该锁已经被占用,此时,会陷入阻塞等待状态。

     int pthread_mutex_trylock(pthread_mutex_t *mutex);

     如果该锁被占用,则会返回一个errnum,可以通过调用strerror(errnum)来获取错误信息。

  解锁:int pthread_mutex_unlock(pthread_mutex_t *mutex);

3、死锁:死锁一般有两种情况。

    第一种是已经给上了一把锁,这时候你忘记你已经上了一把锁,这时候你又上了一把锁,这时候就会陷入阻塞等待状态,或者是又上了另一把锁,这时候其他线程要加锁时,也会因为原来的锁没释放,陷入阻塞等待状态;

    第二种是交叉锁,比如线程a和线程b同时拥有两把锁才能进行任务执行,这时候a拿到锁1,b拿到锁2,a需要继续拿到锁2才能只能,b需要拿到锁1才能执行,这时候,a和b就都会陷入阻塞等待状态,产生死锁。

    解决的办法就是合理分配锁,避免死锁产生。

 4、读写锁:假如有一块共享资源,多个线程同时进行读数据的操作,这时候如果加正常的锁,必然会大大地浪费时间,因为数据本身不会变化;而进行写操作的时候,就不能有其他操作同时访问或者修改该共享资源的数据,这时候,就诞生的一种读写锁来满足这种需求。

    读写锁特点:读共享、写独占、写的优先级高;

    读写锁初始化int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);

           pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

    读写锁销毁:int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

    读锁int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);阻塞

       int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);非阻塞

    写锁int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);非阻塞

       int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);阻塞

    释放锁:int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

原文地址:https://www.cnblogs.com/zz1314/p/12873553.html