Pthread API list

POSIX pthreads

Note: It is assumed that you have a good understanding of the C programming language. If you do not or need to brush up, please review basic C (including pointers and dynamic memory allocation). Here are some resources.

Now that we have a good foundation of thread concepts, lets talk about a particular thread library, POSIX pthreads. The pthread library can be found on almost any modern OS.

A few preliminary steps you should take before beginning any pthread coding is to:

  1. add #include <pthread.h> in your .c or .h header file(s)
  2. define the #define _REENTRANT macro somewhere in a common .h or .c file
  3. In your Makefile make sure gcc links against -lpthread
  4. Optional: add -D_POSIX_PTHREAD_SEMANTICS to your Makefile (gcc flag) for certain function calls like sigwait()

Pthread Basics

Now let's begin our journey into pthreads...

A thread is represented by the type pthread_t. Let's begin by examining most of the pthread creation and initializing functions:

int pthread_create(pthread_t *thread, pthread_attr_t *attr, 
void *(*start_routine)(void *), void *arg);

int pthread_attr_init(pthread_attr_t *attr);

int pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *mutexattr);

int pthread_cond_init(pthread_cond_t *cond,
pthread_condattr_t *cond_attr);

pthread_create() example:

pthread_create(&pt_worker, &thread_attributes, 
thread_function, (void *)thread_args);

The above will create a pthread pt_worker with thread attributes defined in thread_attributes (this argument can be NULL if you want default thread attributes). The thread code is contained in the function thread_function and is passed in a arguments stored in thread_args. The thread_function prototype would look like this:

void *thread_function(void *args);

Immediately after the pthread_create call completes, the thread_function will begin executing.

pthread_XXXX_init() functions initialize thread attributes, mutexes, and condition variables. mutexattr and cond_attr can be NULL if you are using defaults. Mutexes and condition variables can be initialized to default values using the INITIALIZER macros as well. For example:

pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t count_cond = PTHREAD_COND_INITIALIZER;

Pthread Mutexes

To perform locks and unlocks the following functions are available for you:

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

pthread_mutex_lock() is a blocking call. If the thread cannot gain the lock, then the thread will block the thread from proceeding until it obtains the lock. pthread_mutex_trylock() will return immediately if the mutex cannot be locked. To unlock a mutex, simply call pthread_mutex_unlock(). An example on using Pthread mutexes:

pthread_mutex_lock(&count_lock);
count++;
pthread_mutex_unlock(&count_lock);

In the above example, we are incrementing the globally shared count variable. The code between the lock and unlock calls is the critical section. Always try to minimize this section!

Pthread Condition Variables

Here are the pthread condition variable function prototypes:

int pthread_cond_wait(pthread_cond_t *cond,
pthread_mutex_t *mutex);

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

pthread_cond_wait() puts the current thread to sleep. It requires a mutex of the associated shared resource value it is waiting on. pthread_cond_signal() signals one thread out of the possibly many sleeping threads to wakeup. pthread_cond_broadcast() signals all threads waiting on the cond condition variable to wakeup. Here is an example on using pthread condition variables:

pthread_mutex_lock(&count_lock);
while (count < MAX_COUNT) {
pthread_cond_wait(&count_cond, &count_lock);
}
pthread_mutex_unlock(&count_lock);

We are locking the count_lock mutex so we can read the value of count without entering a potential race condition. Notice how the we use a while loop instead of an if statement. This is because of spurious wakeups problem previously mentioned. Just because a thread has been woken does not mean it was due to a pthread_cond_signal() or pthread_cond_broadcast() call. The pthread_cond_wait() call takes the count mutex and condition variable. Why does pthread_cond_wait() require the mutex as well as the conditon variable? It's because it needs to unlock the mutex when going to sleep or you would potentially enter into a deadlock! pthread_cond_wait() if awoken, automatically tries to reacquire the mutex, and will block if it cannot. Using the signal and broadcast functions is self-explanatory. It is recommended that you release any locks that other threads could be waiting on before you signal or broadcast.

Miscellaneous

Here are some suggestions and issues you should consider when creating using pthreads:

  • One thing we have been disregarding in the above discussions is return values. You must check all return values! No exceptions!
  • Sometimes it is desirable for a thread not to terminate (as in the case of the worker thread pool). This can be solved by placing the thread code in an infinite loop and using condition variables.
  • Many of the pthread types can be "free'd" using the pthread_XXXX_destroy() calls.
  • pthread_join() can be used to wait on other threads to finish (if the JOINABLE attribute is set). This is useful in creating barriers or other synchronization windows/points.
  • To set thread attributes, use the pthread_attr_setXXXX() functions. scope, schedpolicy, and detachstate are only some of the useful attributes you can set on your threads.
  • pthread_kill() can be used to deliver signals to specific threads.
  • pthread_self() returns a handle on the calling thread.
  • pthread_once() can be used to ensure that an initializing function within a thread is only run once.
  • There are many, many more useful functions in the pthread library. Consult your man pages or the Nichols text (Appendix C).
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Windows系统中,可以使用WindowsAPI中的关键字`EnterCriticalSection`来替换`pthread_mutex_lock`函数。 `EnterCriticalSection`函数用于进入临界区,确保只有一个线程可以同时访问被保护的资源。下面是使用WindowsAPI替换`pthread_mutex_lock`的示例代码: ```cpp // 定义临界区变量 CRITICAL_SECTION criticalSection; // 初始化临界区 InitializeCriticalSection(&criticalSection); // 进入临界区 EnterCriticalSection(&criticalSection); // 临界区内的代码 // ... // 离开临界区 LeaveCriticalSection(&criticalSection); // 销毁临界区 DeleteCriticalSection(&criticalSection); ``` 在上述示例中,使用`CRITICAL_SECTION`定义一个临界区变量,并使用`InitializeCriticalSection`函数进行初始化。然后,使用`EnterCriticalSection`函数进入临界区,执行需要保护的代码。最后,使用`LeaveCriticalSection`函数离开临界区。最后,使用`DeleteCriticalSection`函数销毁临界区。 请注意,这只是使用WindowsAPI替换`pthread_mutex_lock`函数的一种方式,具体的替换方式可能因代码的具体情况而有所不同。123 #### 引用[.reference_title] - *1* *2* *3* [pthread_mutex_t死锁](https://blog.csdn.net/u010144805/article/details/78438992)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值