Showing posts with label pthread. Show all posts
Showing posts with label pthread. Show all posts

Saturday, April 13, 2013

[C] 线程局部存储 (thread-local storage)

GCC 支持使用线程局部存储(TLS)来方便多线程的编程.通俗来说, TLS就是一些看起来global的变量, 但是它实际上是per-thread的
使用TLS很简单,只需要用__thread关键字来修饰一个"全局变量",比如下面例子里的tid. 它在不同的thread里被输出的时候就是输出不同的值
#include <stdio.h>
#include <pthread.h<
#define NUM_THREADS     5

__thread long tid;

void print_tid() {
    printf("Hello World! It's me, thread #%ld!\n", tid);
}

void *run_thread(void *threadid)
{
    tid = (long)threadid;
    print_tid();
    pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
    pthread_t threads[NUM_THREADS];
    int rc;
    long t;
    for(t=0; t<NUM_THREADS; t++){
        rc = pthread_create(&threads[t], NULL, run_thread, (void *)t);
        if (rc){
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
    }

    /* Last thing that main() should do */
    pthread_exit(NULL);
}
运行
$ gcc test_tls.c
$ ./a.out 
Hello World! It's me, thread #0!
Hello World! It's me, thread #1!
Hello World! It's me, thread #2!
Hello World! It's me, thread #3!
Hello World! It's me, thread #4!

参考

GCC对TLS的支持

Tuesday, January 11, 2011

[Linux]pthread

文档

史上最好的pthread Tutorial/Reference


使用

Thread
pthread_t mythread;
pthread_create(&mythread, NULL, myfunc, NULL);
pthread_join(mythread, NULL);
Mutex
1 初始化一个mutex有两种方式, 可以动态的声明:
pthread_mutex_t mymutex
pthread_mutex_init(&mymutex, NULL); 
也可以静态的声明:
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
2 使用mutex来serialize一段程序. mutex就好比一把锁,被锁住的程序段(pthread_mutex_lock和pthread_mutex_unlock两个语句间的code)在同一时间只能被一个thread执行. 其他需要执行这段程序的thread都会在pthread_mutex_lock这里被卡住,直到mutex被unlock才能有一个thread接着往下执行.
pthread_mutex_lock (&mymutex);
dotstr.sum += mysum;
pthread_mutex_unlock (&mymutex);
3 销毁一个mutex
pthread_mutex_destroy(&mymutex);

Spinlock
spinlock是轻量级的lock机制,比较mutex等机制,节省了process re-scheduling以及context switch等开销,所以如果确信thread不会被block很久,spinlock会非常有效.

1 申明一个spinlock
pthread_spinlock_t myspinlock;
pthread_spin_lock(&myspinlock);
2 使用spinlock上锁
pthread_spin_lock(&myspinlock);
critialnum += 1;
pthread_spin_unlock(&myspinlock);
3 销毁
pthread_spin_destroy(&myspinlock);

在MacOS 上, spinlock的原语与linux上的有所不同.
#include <libkern/osatomic.h>
OSSpinLock mylock = OS_SPINLOCK_INIT;
OSSpinLockLock(&mylock);
OSSpinLockUnlock(&mylock);

Misc

Linux上thread的实现和其他UNIX系统有一个重要区别: Linux上pthread_create实际上用一个process来运行一个thread. 所以每个thread都有自己的pid,也有自己的tid.同一个进程中的thread有同样的pid但是不同的tid. 可以用下面的代码查看pid或者tid
fprintf (stderr, "thread pid is %d\n", (int) getpid ());
fprintf (stderr, "thread tid is %d\n", (int) gettid ());