线程Threading

Multithreading 多线程

多线程的6个主要好处

  • Programming abstraction
  • Parallelism
  • Improving responsiveness
  • Blocking I/O
  • Context switching
  • Memory savings

Costs of Multithreading

不会用,用不好是最大的问题。

Alternatives to Multithreading

Threading Models

User-Level Threading

Hybrid Threading

Coroutines and Fibers

Threading Patterns

在创建一个多线程应用的时候最重要的就是决定线程模型。

Thread-per-Connection

Event-Driven Threading

Concurrency, Parallelism, and Races

Race Conditions

Pthread API

Creating Threads

#include <pthread.h>
int pthread_create (pthread_t *thread,
                                const pthread_attr_t *attr,
                                void *(*start_routine) (void *),
                                 void *arg);
void *start_thread(void *arg);

pthread_t tread;
int ret;
ret = pthread_create (&thread, NULL, start_routine, NULL);
if (!ret) {
        errno = ret;
        perror("pthread_create");
        return -1; 
}
 /* a new thread is created and running start_routine concurrently ... */

Thread IDs

线程可以通过pthread_self()函数在运行时获得它的TID:

#include <pthread.h>
pthread_t pthread_self (void);

用法很简单,因为函数不会失败:

const pthread_t me = pthread_self ();
Comparing thread IDs
#include <pthread.h>
int pthread_equal (pthread_t t1, pthread_t t2);
int ret;
ret = pthread_equal(thing1, thing2);
if (ret != 0)
      printf("The TIDs are equal!\n");
else
      printf("The TIDs are unequal!\n");

Terminating Threads

线程的终结有三种方式:

  1. 如果线程从start_routine返回,它将终止。这类似于main()的“从末尾结束”。
  2. 如果线程调用pthread_exit()函数,这类似于调用exit()。
  3. 如果线程通过pthread_cancel()函数被另一个线程取消,则它终止。这类似于通过kill()发送SIGKILL信号。

Terminating yourself

#include <pthread.h>
void pthread_exit (void *retval);

Terminating others

#include <pthread.h>
int pthread_cancel (pthread_t thread);

成功返回0,否则返回并设置errno

int ret;
/* `thread' is the thread ID of the to-terminate thread */
ret = pthread_cancel (thread);
if (ret) {
      errno = ret;
      perror ("pthread_cancel");
       return -1;
 }
int unused;
int ret;
ret = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &unused);
if (ret) {
    errno = ret;
    perror ("pthread_setcancelstate");
    return -1;
 }
ret = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &unused);
if (ret) {
      errno = ret;
      perror ("pthread_setcanceltype");
      return -1;
}

Joinging and Detaching Threads

Joining threads

Joining允许一个线程在等待另一个线程终止时阻塞

#include <pthread.h>
int pthread_join(pthread_t thread,  void **retval);

调用成功后,调用线程就会被阻塞,直到线程指定的线程终止为止(如果线程已经终止,那么就会直接返回)。

int ret;
/* join with `thread' and we don't care about its return value */
    ret = pthread_join (thread, NULL);
    if (ret) {
        errno = ret;
        perror ("pthread_join");
        return -1;
 }

Detaching threads

#include <pthread.h>
int pthread_detach (pthread_t thread);

A Threading Example

#include <stdio.h>
#include <pthread.h>
void * start_thread (void *message) {
        printf ("%s\n", (const char *) message);
        return message; 
}
int main (void) {
        pthread_t thing1, thing2;
        const char *message1 = "Thing 1";
        const char *message2 = "Thing 2";
        /* Create two threads, each with a different message. */
        pthread_create (&thing1, NULL, start_thread, (void *)       message1);
        pthread_create (&thing2, NULL, start_thread, (void *) message2);
/*
 * Wait for the threads to exit. If we didn't join here,
 * we'd risk terminating this main thread before the
 * other two threads finished.
 */
pthread_join (thing1, NULL);
pthread_join (thing2, NULL);
return 0; 
}

Pthread Mutexes

class ScopedMutex {
public:
        ScopedMutex (pthread_mutex_t& mutex) :mutex_ (mutex) {
                pthread_mutex_lock (&mutex_);
        }
        ~ScopedMutex ()
        {
            pthread_mutex_unlock (&mutex_);
        }
private:
         pthread_mutex_t& mutex_;
};
//only one customer can withdraw
money at a time
static pthread_mutex_t the_mutex = PTHREAD_MUTEX_INITIALIZER;
int withdraw (struct account *account, int amount) {
        pthread_mutex_lock (&the_mutex);
        const int balance = account->balance;
        if (balance < amount) {
              pthread_mutex_unlock (&the_mutex);
              return -1;
         }
        account->balance = balance - amount;
        pthread_mutex_unlock (&the_mutex);
        disburse_money (amount);
        return 0;
 }
// we allow the bank to process other customers’ withdraws in parallel.
//define the lock in account struct
int withdraw (struct account *account, int amount) {
        pthread_mutex_lock (&account->mutex);
        const int balance = account->balance;
        if (balance < amount) {
              pthread_mutex_unlock (&account->mutex);
               return -1;
         }
        account->balance = balance - amount;
        pthread_mutex_unlock (&account->mutex);
        disburse_money (amount);
        return 0;
 }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容