c/c++线程--2线程同步

19 篇文章 0 订阅
3 篇文章 0 订阅

c/c++线程--2线程同步


线程同步的方式
1.互斥锁
2.条件变量
3.读写锁

异步方式
信号

同步方式:
3种锁都需要创建和销毁。还有属性参数,默认属性的话,这个参数传NULL。

互斥锁通信机制

  • 二元变量,解决线程间同步问题。
  • 同步:先后顺序。
  • 以排他方式防止数据结构被并发的修改;

控制逻辑:
a.访问前申请,如果处于开锁状态,则申请到该锁,并占有。
如果处于锁定状态,默认阻塞当前线程。
b.只有锁定该互斥锁的线程才能释放该互斥锁,其他线程的操作无效。


初始化,销毁互斥锁
互斥锁,互斥锁属性的变量类型
pthread_mutex_t
pthread_mutexattr_t


/// 成功返回0
/* Initialize a mutex.  */
extern int pthread_mutex_init (pthread_mutex_t *__mutex,
			       const pthread_mutexattr_t *__mutexattr)
     __THROW __nonnull ((1));


/* Destroy a mutex.  */
extern int pthread_mutex_destroy (pthread_mutex_t *__mutex)
     __THROW __nonnull ((1));


申请互斥锁
/// 非阻塞
/* Try locking a mutex.  */
extern int pthread_mutex_trylock (pthread_mutex_t *__mutex)
     __THROWNL __nonnull ((1));


/// 阻塞
/* Lock a mutex.  */
extern int pthread_mutex_lock (pthread_mutex_t *__mutex)
     __THROWNL __nonnull ((1));

释放互斥锁

/// !!拥有该锁的线程才能开锁。
/* Unlock a mutex.  */
extern int pthread_mutex_unlock (pthread_mutex_t *__mutex)
     __THROWNL __nonnull ((1));


条件变量通信机制

不仅互斥的访问变量,而且当且仅当满足一定条件时,线程才会执行。
如果只使用互斥锁,那么当出现满足的条件时,还要竞争资源。因此,用互斥锁目标线程可能得不到执行的机会。

条件变量解决:
根据保护数据的当前值来调整线程的行为;类似于信号。
条件变量不能单独使用,必须和互斥锁一起使用。
每个线程对应函数的第一条语句使用锁定互斥量的语句,最后一条语句使用解锁互斥量的语句。


条件变量

pthread_cond_t

 
pthread_condattr_t


a.创建,销毁

/* Initialize condition variable COND using attributes ATTR, or use
   the default values if later is NULL.  */
extern int pthread_cond_init (pthread_cond_t *__restrict __cond,
			      const pthread_condattr_t *__restrict __cond_attr)
     __THROW __nonnull ((1));


/* Destroy condition variable COND.  */
extern int pthread_cond_destroy (pthread_cond_t *__cond)
     __THROW __nonnull ((1));

b.等待等待之前要加互斥锁。

阻塞时,隐含释放关联的互斥锁。没唤醒时,隐含加锁。

/* Wait for condition variable COND to be signaled or broadcast.
   MUTEX is assumed to be locked before.


   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
			      pthread_mutex_t *__restrict __mutex)
     __nonnull ((1, 2));
     
/* Wait for condition variable COND to be signaled or broadcast until
   ABSTIME.  MUTEX is assumed to be locked before.  ABSTIME is an
   absolute time specification; zero is the beginning of the epoch
   (00:00:00 GMT, January 1, 1970).


   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
				   pthread_mutex_t *__restrict __mutex,
				   const struct timespec *__restrict __abstime)
     __nonnull ((1, 2, 3));


c. 唤醒

隐含释放关联的互斥锁。
即使没有线程相应,也会返回成功。
/// 唤醒一个
/* Wake up one thread waiting for condition variable COND.  */
extern int pthread_cond_signal (pthread_cond_t *__cond)
     __THROWNL __nonnull ((1));


/// 唤醒所有
/* Wake up all threads waiting for condition variables COND.  */
extern int pthread_cond_broadcast (pthread_cond_t *__cond)
     __THROWNL __nonnull ((1));    

在我看来,条件变量更像是一种信号。 

程序架构
生产者-消费者

putData()
{
lock();
while(仓库满)
{
wait(hasSlot);
}
put(data);
signal(hasData);
unlock();
}

getData()
{
lock();
while(仓库空)
{
wait(hasData);
}
data = get();
signal(hasSlot);
unlock();
}

读写锁通信机制

互斥锁,条件变量都是互斥的访问临街资源。
对于数据的读写操作来说,写写和读写冲突的。如果只是读操作,那么可以不冲突。
如果采用排他的机制来操作,可能会降低效率。
读写锁,就可以解决这样的问题。和数据库的逻辑一样。

控制逻辑:
  • 如果申请了读锁,其他线程也可以申请读锁,但是不能申请写锁。
  • 如果申请了写锁,其他线程既不能申请读锁,也不能申请写锁。
读写锁变量
/* Data structure for read-write lock variable handling.  The
   structure of the attribute type is not exposed on purpose.  */
pthread_rwlock_t rwlock;
pthread_rwlockattr_t rwlockattr;

a. 创建,销毁
/* Initialize read-write lock RWLOCK using attributes ATTR, or use
   the default values if later is NULL.  */
extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
				const pthread_rwlockattr_t *__restrict
				__attr) __THROW __nonnull ((1));


/* Destroy read-write lock RWLOCK.  */
extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock)
     __THROW __nonnull ((1));

b. 申请,释放
申请读锁
/* Acquire read lock for RWLOCK.  */
extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock)
     __THROWNL __nonnull ((1));


/// 非阻塞
/* Try to acquire read lock for RWLOCK.  */
extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
  __THROWNL __nonnull ((1));

申请写锁
/* Acquire write lock for RWLOCK.  */
extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock)
     __THROWNL __nonnull ((1));

/// 非阻塞
/* Try to acquire write lock for RWLOCK.  */
extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
     __THROWNL __nonnull ((1));

释放锁--无论是读锁还是写锁
/* Unlock RWLOCK.  */
extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock)
     __THROWNL __nonnull ((1));

说明:

释放逻辑

(1).如果释放读锁,但还有其他线程占用读锁,读锁依然锁定。没有,则解锁。
(2).如果释放写锁,则直接解锁。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值