2007-01-12

create a thread

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

第一个参数是thread_id,第二个是attribut(一般为NULL),后两个是call_back func. & it's arg.

Example: [$ cc thread.c -othread -lpthread]
#include <pthread.h>
#include <stdio.h>
/* Prints x's to stderr. The parameter is unused. Does not return. */
void* print_xs (void* unused)
{
    while (1)
    fputc ('x', stderr);
    return NULL;
}
/* The main program. */
int main ()
{
    pthread_t thread_id;
    /* Create a new thread. The new thread will run the print_xs
    function. */
    pthread_create (&thread_id, NULL, &print_xs, NULL);
    /* Print o's continuously to stderr. */
    while (1)
    fputc ('o', stderr);
    return 0;
}

想想这个例子输出是什么?从理论上说应该是'x','o'相间无规律排列的字符序列。但我的电脑上运行后是整块整块的'x...','o...'排列(也许从宏观上来说是那样的没错,但总觉得似乎不太理想)。无非是两种情况:时间片和资源争用。而资源争用在这里应该不明显,毕竟原子操作就只是单字符输出。但对于时间片,这也太大了吧~~,不过想想也是哈,现在的CPU动不动就2G、3G的,一个时间片对人类来说没多少但CPU已经可以执行很多条指令了。(现在只好这么解译了)

另外还有:
1. pthread_join
#include <pthread.h>
int pthread_join(pthread_t thread, void **value_ptr);

用于等待thread的返回,第一个参数是thread_id,第二个是thread的返回值(若没有则为NULL)

2. pthread_equal
#include <pthread.h>
int pthread_equal(pthread_t t1, pthread_t t2);

用于比较两个thread_id是否相同(在判断是否是当前线程时比较有用),如:
    if (!pthread_equal (pthread_self (), other_thread_id))
        pthread_join (other_thread_id, NULL);


3. Thread Attributes,如:
pthread_attr_t attr;
pthread_t thread;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread, &attr, &thread_function, NULL);
pthread_attr_destroy (&attr);


4. Thread Cancellation
A canceled thread may later be joined; in fact, you should join a canceled
thread to free up its resources, unless the thread is detached.The return value of a canceled thread is the special value given by PTHREAD_CANCELED.
A thread may be in one of three states with regard to thread cancellation.
1) The thread may be asynchronously cancelable.The thread may be canceled at any point in its execution.
2) The thread may be synchronously cancelable.The thread may be canceled, but not at just any point in its execution. Instead, cancellation requests are queued, and the thread is canceled only when it reaches specific points in its execution.
3) A thread may be uncancelable. Attempts to cancel the thread are quietly ignored.
When initially created, a thread is synchronously cancelable.
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);

4.2.3 When to Use Thread Cancellation
In general, it’s a good idea not to use thread cancellation to end the execution of a
thread, except in unusual circumstances. During normal operation, a better strategy is
to indicate to the thread that it should exit, and then to wait for the thread to exit on
its own in an orderly fashion.We’ll discuss techniques for communicating with the
thread later in this chapter, and in Chapter 5,“Interprocess Communication.”
例:
int process_transaction (int from_acct, int to_acct, float dollars)
{
    int old_cancel_state;
/* Check the balance in FROM_ACCT. */
    if (account_balances[from_acct] < dollars)
        return 1;
/* Begin critical section. */
    pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old_cancel_state);
/* Move the money. */
    account_balances[to_acct] += dollars;
    account_balances[from_acct] -= dollars;
/* End critical section. */
    pthread_setcancelstate (old_cancel_state, NULL);
    return 0;
}

(P.96 in <Advanced Linux Programming>)
and "Thread in C++" is P.100

还有:
pthread_mutex_t mutex;
pthread_mutex_init (&mutex, NULL);

例:P.104
struct job {
    /* Link field for linked list. */
    struct job* next;
/* Other fields describing work to be done... */
};
/* A linked list of pending jobs. */
struct job* job_queue;
/* A mutex protecting job_queue. */
pthread_mutex_t job_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Process queued jobs until the queue is empty. */
void* thread_function (void* arg)
{
    while (1) {
        struct job* next_job;
        /* Lock the mutex on the job queue. */
        pthread_mutex_lock (&job_queue_mutex);
        /* Now it’s safe to check if the queue is empty. */
        if (job_queue == NULL)
            next_job = NULL;
        else {
            /* Get the next available job. */
            next_job = job_queue;
            /* Remove this job from the list. */
            job_queue = job_queue->next;
        }
        /* Unlock the mutex on the job queue because we’re done with the
         * queue for now. */
        pthread_mutex_unlock (&job_queue_mutex);
        /* Was the queue empty? If so, end the thread. */
        if (next_job == NULL)
            break;
        /* Carry out the work. */
        process_job (next_job);
        /* Clean up. */
        free (next_job);
    }
return NULL;
}


//EOF

0 comments: