Friday, January 31, 2014

pthread - Synchronization

Three types of mutual exclustion ways in pthreads.

1) mutex

Accepted one. Used widely. Efficiency is Not bad. Suspend-Waiting mechanism.

2) spin

Same as mutex. But, wait by busy loop. Efficiency will be bad by number of threads.

3) read/write locks

Mostly used when accessing cache information. High class synchronization process. New standard, worst efficient.

Mutex:

Easy to use.
  • int pthread_mutex_init( pthread_mutex_t * mutex, const pthread_mutex_attr_t * mutexattr );
  • int pthread_mutex_destroy( pthread_mutex_t * mutex );
  • int pthread_mutex_lock( pthread_mutex_t * mutex );
  • int pthread_mutex_unlock( pthread_mutex_t * mutex );
  • int pthread_mutex_trylock( pthread_mutex_t * mutex );
Initialize the variable mutex and use pthread_mutex_lock() before critical section and pthread_mutex_unlock() after critical section. If you use pthread_mutex_trylock(), it wil try to lock. If locked by another thread, it will return EBUSY without suspending the task. If the mutex usage is over, it can be destroyed using pthread_mutex_destroy().

pthread_mutexattr_t is used to set the type of mutex and the priority inversion protocol.

The following two methods can be used for initialization and have same meaning.
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_init( &mutex, 0 );
SPIN:

CPU usage will be 100%.
  • int pthread_spin_init( pthread_spinlock_t * __lock, int __pshared )
  • int pthread_spin_destroy( pthread_spinlock_t * __lock )
  • int pthread_spin_lock( pthread_spinlock_t * __lock )
  • int pthread_spin_unlock( pthread_spinlock_t * __lock )
  • int pthread_spin_trylock( pthread_spinlock_t * __lock )
__pshared is used to specify whether this spinlock can be used by other processes or only the threads of this process only.
PTHREAD_PROCESS_PRIVATE - Only for this process. Operation is not guaranteed when used by other processes.
PTHREAD_PROCESS_SHARED - Can be used by other processes

When using spin lock, the switching can be fast to some extent. But, when the number of threads are more than the number of CPUs, the efficiency will degrade sharply.

Spinlock can be implemented using Mutex as in wrap_spin.c

http://en.wikipedia.org/wiki/Inter-process_communication


read-write lock:

When a thread is going to change a content, then it should lock. But, when few threads just want to read the content, there is not need for lock.
mutex/spin do not have such kind of flexibility, but suspends all threads and causes bottleneck.

For example, when access to the cached information etc will only read the contents, simultaneous access also okay. read/write lock is to implement this.

  • int pthread_rwlock_init( pthread_rwlock_t * __rwlock, __const pthread_rwlockattr_t * __attr )
  • 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_timedrdlock( pthread_rwlock_t * __rwlock, __const struct timespec * __abstime )
  • int pthread_rwlock_wrlock( pthread_rwlock_t * __rwlock )
  • int pthread_rwlock_trywrlock( pthread_rwlock_t * __rwlock )
  • int pthread_rwlock_timedwrlock( pthread_rwlock_t * __rwlock, __const struct timespec * __abstime )
  • int pthread_rwlock_unlock( pthread_rwlock_t * __rwlock )

pthread_rwlockattr_t __attr is similar to spin and decides whether can be used across processes.

read/write lock can be implemetned using mutex is shown in wrap_rwlock.c.


  • read_lock
  •     if in the mid of write or there is waiting task for write, then suspends.
  • read_unlock     If not in the middle of read and there is waiting task, the signals(wakes-up) write waiting task.
  • write_lock     if in the mid of read or in the mid of write, then suspends the task.
  • write_unlock     if there is write waiting task then to the write-waiting task, if there is no write-waiting but read-waiting, the to the read waiting task, signal (wake-up) is issued.

  •  But, read-write locks are costly since the condition needs to be checked everytime. So, there is extra processing compared to just locking mutex. So, examine from performance point of view before using it.

     This post has reference from http://codezine.jp/article/detail/1893 (pthreadについて(同期)).

    No comments: