thread

HW pi.c

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

long incircle = 0;
long points_per_thread;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *runner() {
    long incircle_thread = 0;

    unsigned int rand_state = rand();
    long i;
    for (i = 0; i < points_per_thread; i++) {
        /* Was initially using random(), but didn't appear to get performance
         * improvement with threading. random() apparently uses some global state
         * that is shared between threads, and isn't guaranteed to be threadsafe. */
        double x = rand_r(&rand_state) / ((double)RAND_MAX + 1) * 2.0 - 1.0;
        double y = rand_r(&rand_state) / ((double)RAND_MAX + 1) * 2.0 - 1.0;

        if (x * x + y * y < 1) {
            incircle_thread++;
        }
    }

    pthread_mutex_lock(&mutex);
    incircle += incircle_thread;
    pthread_mutex_unlock(&mutex);
}

/* Calculate Pi by the Monte Carlo method. Program arguments are the total number of random
 * points to use in the calculation and the number of threads to use. */
int main(int argc, const char *argv[])
{
    if (argc != 3) {
        fprintf(stderr, "usage: ./pi <total points> <threads>\n");
        exit(1);
    }

    long totalpoints = atol(argv[1]);
    int thread_count = atoi(argv[2]);
    points_per_thread = totalpoints / thread_count;

    /* Tried using clock, but it measures CPU time, not wall clock time,
     * so doesn't demonstrate improvement gained by threading */
    time_t start = time(NULL);

    srand((unsigned)time(NULL));

    pthread_t *threads = malloc(thread_count * sizeof(pthread_t));

    pthread_attr_t attr;
    pthread_attr_init(&attr);

    int i;
    for (i = 0; i < thread_count; i++) {
        pthread_create(&threads[i], &attr, runner, (void *) NULL);
    }

    for (i = 0; i < thread_count; i++) {
        pthread_join(threads[i], NULL);
    }

    pthread_mutex_destroy(&mutex);
    free(threads);

    printf("Pi: %f\n", (4. * (double)incircle) / ((double)points_per_thread * thread_count));
    printf("Time: %d sec\n", (unsigned int)(time(NULL) - start));

    return 0;
}
gcc pi.c -o pi -lpthread

./pi 10 2

http://shihyu.github.io/books/ch35s01.html

创建线程的时候提到一个函数pthread_self,这个函数使POSIX线程库中的一个函数,通过这个函数可以获得线程的ID,可是我们打印出来这个ID会发现这个ID是一个很大的数字。没有得到我们想象的一个数字,其实这个ID是POSIX线程库提供的一个数字,而linux内核中也为这个线程提供了一个ID,这个ID可以通过gettid获得,gettid是linux内核提供的一个系统调用,Glibc没有封装函数,只能通过系统调用实现。

數據類型
pthread_t:線程句柄
pthread_attr_t:線程屬性
線程操縱函數(簡介起見,省略參數)
pthread_create():創建一個線程
pthread_exit():終止當前線程
pthread_cancel():中斷另外一個線程的運行
pthread_join():阻塞當前的線程,直到另外一個線程運行結束
pthread_attr_init():初始化線程的屬性
pthread_attr_setdetachstate():設置脫離狀態的屬性(決定這個線程在終止時是否可以被結合)
pthread_attr_getdetachstate():獲取脫離狀態的屬性
pthread_attr_destroy():刪除線程的屬性
pthread_kill():向線程發送一個信號

同步函數
用於 mutex 和條件變量
pthread_mutex_init() 初始化互斥鎖
pthread_mutex_destroy() 刪除互斥鎖
pthread_mutex_lock():佔有互斥鎖(阻塞操作)
pthread_mutex_trylock():試圖佔有互斥鎖(不阻塞操作)。當互斥鎖空閒時將佔有該鎖;否則立即返回
pthread_mutex_unlock(): 釋放互斥鎖
pthread_cond_init():初始化條件變量
pthread_cond_destroy():銷毀條件變量
pthread_cond_wait(): 等待條件變量的特殊條件發生
pthread_cond_signal(): 喚醒第一個調用pthread_cond_wait()而進入睡眠的線程
Thread-local storage(或者以Pthreads術語,稱作 線程特有數據):
pthread_key_create(): 分配用於標識進程中線程特定數據的鍵
pthread_setspecific(): 為指定線程特定數據鍵設置線程特定綁定
pthread_getspecific(): 獲取調用線程的鍵綁定,並將該綁定存儲在 value 指向的位置中
pthread_key_delete(): 銷毀現有線程特定數據鍵

與一起工作的工具函數
pthread_equal(): 對兩個線程的線程標識號進行比較
pthread_detach(): 分離線程
pthread_self(): 查詢線程自身線程標識號

pthread_create & pthread_join 還沒create thread PID 會跟 TID 相同

getppid // 取得父行程ID getpid // 取得目前ID gettid // 取得目前 Thread ID (TID)

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>

#define gettid() syscall(__NR_gettid)

void *show_message( void *ptr )
{
    char *message;
    message = (char *) ptr;
    int x = 5;
    for(x = 5 ; x > 0 ; --x) {
        printf("the %s thread ppid = %d,pid = %d,tid = %ld.\n",message, getppid(),getpid(),gettid());
        sleep(2);
    }
}

int main() {
    pthread_t thread1;
    pthread_t thread2;

    printf("the main thread ppid = %d,pid = %d,tid = %ld.\n",getppid(),getpid(),gettid());  // 還沒create thread PID 會跟 TID 相同

    pthread_create(&thread1, NULL , show_message , (void*) "Thread 1");
    pthread_create(&thread2, NULL , show_message , (void*) "Thread 2");
    pthread_join( thread1, NULL);
    pthread_join( thread2, NULL);

    return 0;
}
gcc thread_test.c -o thread_test -lpthread

27603 是 shell 的 pid

the main thread ppid = 27603,pid = 31008,tid = 31008.
the Thread 1 thread ppid = 27603,pid = 31008,tid = 31009.
the Thread 2 thread ppid = 27603,pid = 31008,tid = 31010.
the Thread 1 thread ppid = 27603,pid = 31008,tid = 31009.
the Thread 2 thread ppid = 27603,pid = 31008,tid = 31010.
the Thread 1 thread ppid = 27603,pid = 31008,tid = 31009.
the Thread 2 thread ppid = 27603,pid = 31008,tid = 31010.
the Thread 1 thread ppid = 27603,pid = 31008,tid = 31009.
the Thread 2 thread ppid = 27603,pid = 31008,tid = 31010.
the Thread 1 thread ppid = 27603,pid = 31008,tid = 31009.
the Thread 2 thread ppid = 27603,pid = 31008,tid = 31010.
[shihyu-MS-7758 ~]$ echo $$
27603