mutex.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
int value = 0;
pthread_mutex_t mutex;
pthread_mutexattr_t m_attr;
void func_value(void)
{
// This function process the shared data, before calling this function
// mutex must be locked.
value++;
}
void func_2(void)
{
pthread_mutex_lock(&mutex);
func_value();
pthread_mutex_unlock(&mutex);
}
void func_1(void)
{
pthread_mutex_lock(&mutex);
func_value();
pthread_mutex_unlock(&mutex);
}
int main(int argc, char* argv[])
{
//Initialize mutex attribute
pthread_mutexattr_init(&m_attr);
pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_NORMAL);
//Initialize mutex
if(pthread_mutex_init(&mutex, &m_attr) != 0) {
printf("pthread_mutex_init error!\n");
exit(1);
}
func_1();
func_2();
printf("value: %d\n", value);
// Destory the mutex and mutex attribute object
pthread_mutexattr_destroy(&m_attr);
pthread_mutex_destroy(&mutex);
}
shell:
We can extract the common code to update the value, and whenever before updating the value, we should lock the mutex with the caller.
ubuntu@ip-172-31-23-227:~$ ./mutex.out
value: 2
2. Example of usage of recursive lock
mutex.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<time.h>
#include<sys/time.h>
#define SECTONSEC 1000000000
#define USECTONSEC 1000
struct to_info {
void (*to_fn)(void *);
void *to_arg;
struct timespec to_wait;
};
pthread_mutexattr_t attr;
pthread_mutex_t mutex;
int makethread(void *(*fn)(void *), void *arg)
{
int err;
pthread_t tid;
pthread_attr_t attr;
err = pthread_attr_init(&attr);
if(err != 0)
return(err);
err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if(err == 0)
err = pthread_create(&tid, &attr, fn, arg);
pthread_attr_destroy(&attr);
return err;
}
void * timeout_helper(void *arg)
{
struct to_info *tip;
tip = (struct to_info *) arg;
nanosleep(&tip->to_wait, NULL);
(*tip->to_fn)(tip->to_arg);
return 0;
}
void timeout(const struct timespec *period, void (*func)(void*), void *arg)
{
int err;
struct to_info *tip;
tip = (struct to_info*)malloc(sizeof(struct to_info));
tip->to_fn = func;
tip->to_arg = arg;
tip->to_wait.tv_sec = period->tv_sec;
tip->to_wait.tv_nsec = period->tv_nsec;
if(tip != NULL) {
err = makethread(timeout_helper, (void*)tip);
if(err == 0) return;
}
(*func)(arg);
}
void retry(void *arg)
{
pthread_mutex_lock(&mutex);
printf("retry is called!\n");
pthread_mutex_unlock(&mutex);
}
int main(void)
{
int err, condition;
long arg;
struct timespec period;
// Initialize the attribute
if((err = pthread_mutexattr_init(&attr)) != 0) {
printf("pthread_mutexattr_init error!\n");
exit(1);
}
if((err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) != 0) {
printf("can't do the recursive type!\n");
exit(2);
}
if((err = pthread_mutex_init(&mutex, &attr)) != 0) {
printf("pthread_mutex_init error!\n");
exit(3);
}
// Launch the thread
pthread_mutex_lock(&mutex);
period.tv_sec = 1;
period.tv_nsec = 500;
timeout(&period, retry, (void*)arg);
pthread_mutex_unlock(&mutex);
//Wait for 2 seconds to let the thread finish firstly
sleep(2);
exit(0);
}
shell:
Since before launching the timeout in the main function, it already locked the mutex, and when retry is called, it would lock again. We have to make it recursive mutex to make it work.
ubuntu@ip-172-31-23-227:~$ ./mutex.out
retry is called!
2. Reader-Writer lock attributes and Condition Variable Attributes
ubuntu@ip-172-31-23-227:~$ less /usr/include/pthread.h
......
/* Initialize attribute object ATTR with default values. */
extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr)
__THROW __nonnull ((1));
/* Destroy attribute object ATTR. */
extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr)
__THROW __nonnull ((1));
/* Return current setting of process-shared attribute of ATTR in PSHARED. */
extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *
__restrict __attr,
int *__restrict __pshared)
__THROW __nonnull ((1, 2));
/* Set process-shared attribute of ATTR to PSHARED. */
extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr,
int __pshared)
__THROW __nonnull ((1));
......
extern int pthread_condattr_init (pthread_condattr_t *__attr)
__THROW __nonnull ((1));
/* Destroy condition variable attribute ATTR. */
extern int pthread_condattr_destroy (pthread_condattr_t *__attr)
__THROW __nonnull ((1));
/* Get the process-shared flag of the condition variable attribute ATTR. */
extern int pthread_condattr_getpshared (const pthread_condattr_t *
__restrict __attr,
int *__restrict __pshared)
__THROW __nonnull ((1, 2));
/* Set the process-shared flag of the condition variable attribute ATTR. */
extern int pthread_condattr_setpshared (pthread_condattr_t *__attr,
int __pshared) __THROW __nonnull ((1));
......
Similar from mutex attribute.
No comments:
Post a Comment