【问题标题】:C: Printing out multiple threads' ID's before they execute anything?C:在执行任何操作之前打印出多个线程的 ID?
【发布时间】:2020-11-10 04:52:41
【问题描述】:

我想根据用户希望创建的数量生成多个线程,每个线程都执行一个函数“readFiles”。但是,在线程可以分别执行 readFiles 中的任何有意义的代码(由 "..." 表示)之前,我希望所有线程都在一种介绍性通知消息中打印出它们的线程 ID,所以像......

"Thread ID _____ is processing!"
"Thread ID _____ is processing!"
"Thread ID _____ is processing!"
    ...
    ...
    ...

...但显然,对于我拥有的代码,每个线程一次只运行一个,因此线程 ID 仅在每个新线程开始执行有意义的代码时打印出来,所以这...

"Thread ID _____ is processing!"
    ...
"Thread ID _____ is processing!"
    ...
"Thread ID _____ is processing!"
    ...

在我对每个特定的新线程调用 pthread_create() 之前,有没有办法获取线程 ID?或者有没有一种方法可以让这些线程(它们应该同时运行),推迟或暂停它们在 readFiles (它们的 "..." )中执行有意义的代码,直到它们各自打印出首先是线程 ID 消息?非常感谢大家!!!这是我的代码,可让您更好地了解我目前拥有的内容...

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

uint64_t gettid()
{
    pthread_t actual_tid = pthread_self();
    uint64_t threadId = 0;
    memcpy( &threadId, &actual_tid, sizeof( actual_tid ) );
    return threadId;
}


void *readFiles( void *args )
{
    pthread_mutex_lock(&mutex);


    uint64_t current_id = gettid();
    printf("Thread id = ");
    printf("%" PRIu64 , current_id );

    ...
    ...
    ...

    pthread_mutex_unlock(&mutex);
}


void alphabetcountmulthreads(int num_threads)
{

    pthread_t ids[num_threads];

    for ( int t = 0; t < num_threads; t++ )
    {
        
        if ( pthread_create( &ids[t], NULL, &readFiles, NULL ) != 0 )
        {
            fprintf( stderr, "error: Cannot create thread # %d\n", t );
            break;
        }
    }

    for ( int u = 0; u < num_threads; ++u )
    {
        if ( pthread_join( ids[u], NULL ) != 0 )
        {
            fprintf( stderr, "error: Cannot join thread # %d\N", u );
        }
    }    

}

【问题讨论】:

    标签: c linux pthreads posix pthread-join


    【解决方案1】:

    您可以通过多种方式完成此操作。您可以使用信号 - 让每个线程向各种监视线程发送信号,然后等待被告知运行。一旦监视器线程接收到所有信号,它就会向等待的线程发出信号以继续。您还可以使用条件变量或互斥锁实现类似的解决方案,以锁定线程,直到所有线程都打印了它们的 ID。

    【讨论】:

    • 为什么不只是一个简单的条件变量?或者甚至让线程在创建线程时持有一个互斥锁,直到它打印出所有线程 ID 才释放它?然后,每个线程都可以暂时获取/释放互斥锁,以确保在创建线程打印其 ID 之前它无法取得进展。
    【解决方案2】:

    实现线程池的一种简单方法是,在所有线程开始实际工作之前,每个线程都有机会进行准备工作,即拥有一个额外的启动互斥锁、相关的条件变量和一个就绪线程计数器:

    static pthread_mutex_t  prep_mutex = PTHREAD_MUTEX_INITIALIZER;
    static pthread_cond_t   prep_cond = PTHREAD_COND_INITIALIZER;
    static volatile size_t  prep_count = 0;
    
    static pthread_mutex_t  thread_mutex = PTHREAD_MUTEX_INITIALIZER;
    static volatile size_t  thread_count = 0;
    
    static inline pid_t gettid(void) { return syscall(SYS_gettid); }
    
    static void *thread_function(void *idref)
    {
        /* Get the number/index of this thread. */
        const size_t  num = *(pid_t *)idref;
        const pid_t   tid = gettid();
    
        /* Replace it with the Linux tid. */
        *(pid_t *)idref = tid;
    
        /* Block here until preparatory work can be done. */
        pthread_mutex_lock(&prep_mutex);
    
        printf("Thread %zu of %zu has started.\n", id + 1, thread_count);
        fflush(stdout);
    
        prep_count++;
        pthread_cond_signal(&prep_cond);
        pthread_mutex_unlock(&prep_mutex);
    
        /* Block until actual work can start. */
        pthread_mutex_lock(&thread_mutex);
        ...
    

    创建线程池时,创建者持有两个互斥锁。当它准备好让线程开始准备工作时,它会释放prep_mutex,等待prep_cond,直到有足够数量的线程完成准备工作(prep_count 足够高)。然后,它释放thread_mutex

    int start_threads(size_t max_count)
    {
        pthread_t       thread_id[max_count];
        pid_t           linux_tid[max_count];
        pthread_attr_t  attrs;
        int             err = 0;
    
        /* Assume no threads currently running */
        prep_count = thread_count = 0;
    
        /* Shrink stack size; the default is too large. */
        pthread_attr_init(&attrs);
        pthread_attr_setstacksize(&attrs, 2*PTHREAD_STACK_MIN);
    
        /* Grab the mutexes, so the threads will block initially. */
        pthread_mutex_lock(&prep_mutex);
        pthread_mutex_lock(&thread_mutex);
    
        while (thread_count < max_count) {
            linux_tid[thread_count] = thread_count;
            err = pthread_create(thread_id + thread_count, &attrs,
                                 thread_function, linux_tid + thread_count);
            if (err)
                break;
    
            thread_count++;
        }
    
        /* Attributes are no longer needed. */
        pthread_attr_destroy(&attrs);
    
        /* No threads created at all? */
        if (thread_count < 1) {
            pthread_mutex_unlock(&prep_mutex);
            pthread_mutex_unlock(&thread_mutex);
            /* Return failure. */
            return err;
        }
    
        /* All threads have now been created; let them do prep work. */
        while (prep_count < thread_count) {
            pthread_cond_wait(&prep_cond, &prep_mutex);
        }
        pthread_mutex_unlock(&prep_mutex);
    
        /* All threads have finished their prep work; start working. */
        pthread_mutex_unlock(&thread_mutex);
    
        ...
    

    上面创建了最多max_num 线程,它们的pthread ID 为thread_id[],它们的Linux tid 为linux_tid[]

    当线程启动时,它会获得一个指向存储 Linux tid 的位置的指针。最初,它包含线程的索引(“线程号”,从 0 开始),因此thread_function 将其作为num 获取,以tid 获得Linux tid,并将其存储到作为参数给定的位置.这样,原始线程和创建的线程都知道索引(num)、pthread ID(thread_id[]pthread_self())和 Linux tid(linux_tid[]tid)。

    注意在pthread_create() 调用中如何取消引用数组。如果array 是一个数组,而index 是它的索引,那么&amp;(array[index]) == array + index

    上面,start_threads() 函数并不假定它可以启动所有max_num 线程。如果它不能创建任何线程,它会返回非零的errno 数字,但如果它可以创建至少一个线程,一旦线程可以抓取prep_mutexthread_count 将反映他们帮派中正确的线程数. (没有理由仅仅因为您只能创建 53 个工作线程而不是 54 个而失败。)

    【讨论】:

      猜你喜欢
      • 2015-04-05
      • 1970-01-01
      • 2012-02-01
      • 2022-10-04
      • 2016-02-21
      • 2011-06-16
      • 2019-02-22
      • 2015-01-26
      • 1970-01-01
      相关资源
      最近更新 更多