Resumo dos pontos de conhecimento comuns de multithreading Linux

Notas de função comumente usadas de multithreading Linux

Uso da função thread

[Tipo de TID: pthread_t]

  • pthread_t é um tipo de dados estruturado, portanto, as implementações de sistemas operacionais portáteis não podem tratá-lo como um número inteiro
  • Linux 3.2.0 usa um inteiro longo sem sinal para representar o tipo de dados pthread_t

[Comparação do tópico TID: pthread_equal]

#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);
// 若相等,返回非0数值;否则,返回0

[Obtenha seu próprio ID de tópico: pthread_self]

  • Ao imprimir com printf, use "% lu" para imprimir o valor do tipo pthread_t
#include <pthread.h>
pthread_t pthread_self(void); 
// 返回调用线程的线程ID

[Gettid () para obter o título do tópico]

  • A função gettid () pode obter o tid do thread, mas a glibc não implementa esta função, ela só pode ser obtida através da chamada do sistema Linux syscall (<sys / syscall.h>)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h> 

void *hello()
{
	printf("child,the tid=%lu,pid=%ld\n",pthread_self(),syscall(SYS_gettid));
}

int main(int argc,char *agrv[])
{
	pthread_t thread_id;
	pthread_create(&thread_id,NULL,(void *)*hello,NULL);
	
	printf("parent,the tid=%lu,pid=%ld\n",pthread_self(),syscall(SYS_gettid));
	pthread_join(thread_id,NULL);
}
  • Observação:
    • Use o método acima para verificar: o PID do thread principal é o mesmo que o PID do processo
    • Quando nenhum encadeamento é criado no processo, o processo principal é equivalente a um encadeamento principal, porque o ID do processo e o encadeamento são os mesmos

[Função de criação de thread: pthread_create]

#include <pthread.h>
int pthread_create(
	pthread_t              *restrict tidp,        //当pthread_create成功返回时,新创建的线程ID会被设置到tidp所指向的内存单元中
	const pthread_attr_t   *restrict attr,        //atrr参数用于指定线程创建时的初始化属性。值为NULL时,创建一个具有默认属性的线程。
	void                   *(*start_rtn)(void *), //新创建的线程从start_rtn函数的地址开始运行。该函数只有一个无类型指针参数arg,返回值为void*类型
	void                   *restrict  arg         //如果需要向start_rtn函数传递的参数有一个以上,需要把这些参数放到一个结构中,传递该结构的地址
	);
  • valor de retorno:
    • Sucesso: retorno 0
    • Erro: retorna o número do erro sem definir errno
  • Caso 1
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
pthread_t ntid;
 
void printids(const char *s){
    pid_t pid;
    pthread_t tid;
    pid = getpid();
    tid = pthread_self();
    printf("%s pid %lu tid %lu (0x%lx)\n", s, (unsigned long)pid,(unsigned long)tid, 
    (unsigned long)tid);
}
 
void *thr_fn(void *arg){
    printids("new thread: ");
    return((void *)0);
}
 
int main(void)
{
    int err;
    //create thread
    err = pthread_create(&ntid, NULL, thr_fn, NULL);
    if (err != 0)
        printf("can’t create thread\n");
    printids("main thread:");
    sleep(1);
    exit(0);
}
  • Caso 2
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h> 

struct message
{
	int i;
	int j;
};

void *hello(struct message *str)
{
	printf("child,the tid=%lu,pid=%ld\n",pthread_self(),syscall(SYS_gettid));
	printf("the arg.i is %d,arg.j is %d\n",str->i,str->j);
}
 
int main(int argc,char *agrv[])
{
	struct message test;
	pthread_t thread_id;
	test.i=10;
	test.j=20;
	pthread_create(&thread_id, NULL,(void *)*hello,&test);
	printf("parent,the tid=%lu,pid=%ld\n",pthread_self(),syscall(SYS_gettid));
	pthread_join(thread_id,NULL);
}

[Estrutura de atributos do tópico: pthread_attr_t]

  • O conteúdo dessa estrutura contém o valor do atributo do encadeamento e o parâmetro 2 de pthread_create usa essa estrutura para definir o valor do atributo inicial para o encadeamento.

[Criação e destruição da estrutura de atributos do thread]

int pthread_attr_init(pthread_attr_t *attr);
  • Função: usada para inicializar o valor do atributo do thread
  • Nota: Depois de chamar esta função, os atributos da estrutura de atributos são valores padrão do sistema.Se você deseja definir outros atributos, você precisa chamar funções diferentes para defini-los.
int pthread_attr_destroy(pthread_attr_t *attr);
  • Função: usada para inicializar (destruir) atributos. Se os atributos do thread inicializados pela função pthread_attr_init forem alocados dinamicamente, então esta função irá liberar o espaço de memória dos atributos do thread
  • A função pthread_attr_destory inicializa o objeto de atributo com um valor inválido, portanto, após desinicializar o atributo com esta função, o atributo não pode ser usado pela função pthread_create.

[Método de terminação de thread]

  • Os três métodos a seguir são para encerrar o encadeamento e interromper seu fluxo de controle sem encerrar todo o processo normalmente:
    • ① O encadeamento pode simplesmente retornar da rotina de inicialização e o valor de retorno é o código de saída do encadeamento
    • ② O thread pode ser cancelado por outros threads no mesmo processo ( pthread_cancel )
    • ③Thread chama pthread_exit

[Função de saída do tópico: pthread_exit]

#include <pthread.h>
void pthread_exit(void *rval_ptr);
  • Função: o thread chama esta função para se encerrar
  • Parâmetro: rval_ptr é um ponteiro sem tipo e o conteúdo pode ser definido neste ponteiro para sair do processo (geralmente para definir o código de finalização).
    • Outros threads no processo também podem acessar este ponteiro chamando a função pthread_join
#include<pthread.h>
#include<stdlib.h>
#include<stdio.h>
void * thr_fn1(void *arg){
    printf("thread 1 returning\n");
    return((void *)1);
}
void *thr_fn2(void *arg){
    printf("thread 2 exiting\n");
    pthread_exit((void *)2);
}
int main(void)
{
    int err;
    pthread_t tid1, tid2;
    void *tret;
 
    err = pthread_create(&tid1, NULL, thr_fn1, NULL);//创建线程1
    if (err != 0)
        printf("can’t create thread 1\n");
    err = pthread_create(&tid2, NULL, thr_fn2, NULL);//创建线程2
    if (err != 0)
        printf("can’t create thread 2\n");
 
    err = pthread_join(tid1, &tret);//等待线程1
    if (err != 0)
        printf("can’t join with thread 1\n");
    printf("thread 1 exit code %ld\n", (long)tret);
    
    err = pthread_join(tid2, &tret);//等待线程2
    if (err != 0)
        printf("can’t join with thread 2\n");
    printf("thread 2 exit code %ld\n", (long)tret);
   
     exit(0);
}

[Função de espera de thread pthread_join]

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
  • Valor de retorno: retornar 0 em caso de sucesso; retornar o número do erro em caso de falha
  • Função: usada para esperar o fim do thread especificado pelo parâmetro 1
  • Esta função irá bloquear até que a thread especificada chame pthread_exit, retorne da thread inicial ou seja cancelada, então esta função retorna
  • parâmetro:
    • Parâmetro 1: especifique o ID do segmento de espera
    • Parâmetro 2:
      • Preencher NULL: Obtenha as informações de encerramento do thread em espera. Se você não estiver interessado nas informações de encerramento do thread, poderá defini-lo como NULL.
      • Não vazio: Se a thread simplesmente retornar de sua rotina de retorno, rval_ptr conterá o código de retorno.
      • Se o thread for cancelado, a unidade de memória especificada por rval_ptr é definida como PTHREAD_CANCELED
  • A relação entre o uso da função thread_join e separação de thread:
    • Chame pthread_join para esperar por um thread. Após o término do thread em espera, ele será colocado em um estado separado, para que os recursos usados ​​pelo thread possam ser restaurados
    • Se pthread_join for chamado para esperar por um thread, se o thread já estiver em um estado separado (por exemplo, a função pthread_detach é chamada), a chamada de pthread_join falhará e retornará EINVAL, embora este comportamento esteja relacionado à implementação específica

[Função de cancelamento de thread: pthread_cancel]

#include <pthread.h>
int pthread_cancel(pthread_t tid);
  • Valor de retorno: retorna 0 se for bem sucedido; caso contrário, retorna o número do erro
  • Função: Thread pode solicitar o cancelamento de outros threads no mesmo processo por meio de pthread_cancel
  • pthread_cancel não espera o encadeamento terminar, ele apenas faz uma solicitação
  • parâmetro:
    • ID da discussão que precisa ser cancelada
  • Precauções:
    • Por padrão, a função pthread_cancel fará com que a thread identificada por tid se comporte como se estivesse chamando a função pthread_exit com o parâmetro PTHREAD_CANCELED, mas a thread cancelada pode escolher ignorar o cancelamento ou controlar como ela é cancelada

[Ponto de cancelamento do tópico]

  • Conceito: O sistema personaliza alguns pontos de cancelamento de thread. Quando um encadeamento recebe uma solicitação de cancelamento de outro encadeamento, se não foi executado até o ponto de cancelamento, o encadeamento continuará a ser executado até chegar a um determinado ponto de cancelamento, o encadeamento é realmente cancelado. A tecnologia de ponto de cancelamento de encadeamento também é chamada "adiamento". cancelar "
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
 
void *thread_func(void* arg);
 
int main()
{
    pthread_t tid;
    int *thread_exit_code=malloc(sizeof(int));
    if(pthread_create(&tid,NULL,thread_func,NULL)!=0){
        fprintf(stdout,"pthread_create error\n");
        exit(EXIT_FAILURE);
    }
 
    //进程休眠1秒,然后取消子线程
    sleep(1);
    if(pthread_cancel(tid)!=0){
        fprintf(stdout,"pthread_cancel error\n");
        exit(EXIT_FAILURE);
    }
 
    printf("pthread_cancel filaed\n");
    
    //睡眠8秒之后取消线程失败了,因为线程已经退出了
    sleep(8);
    if(pthread_cancel(tid)!=0){
        fprintf(stdout,"pthread_cancel error\n");
        exit(EXIT_FAILURE);
    }
    
    printf("kill thread success\n");
 
    if(pthread_join(tid,(void*)&thread_exit_code)==0){
        printf("pthread_join success,exit_code is %d\n",(int)*thread_exit_code);
    }else{
        fprintf(stdout,"pthread_join error\n");
        exit(EXIT_FAILURE);
    }
 
    exit(0);
}
 
void *thread_func(void* arg)
{
    int exit_code,i;
    
    //进入之后,先设置自己为不可取消状态
    printf("I am thread,now my cancle type is disable\n");
    if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL)!=0){
        fprintf(stdout,"pthread_setcancelstate error\n");
        exit_code=-1;
        pthread_exit(&exit_code);
    }
   
 
    for(i=1;i<=3;i++){
        sleep(1);
        printf("thread running (%d)\n",i);
    }
 
    //休眠3秒之后之后设置线程可以被取消
    printf("I am thread,now my cancle type is enable\n");
    if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL)!=0){
        fprintf(stdout,"pthread_setcancelstate error\n");
        exit_code=-1;
        pthread_exit(&exit_code);
    }
    
    printf("thread sleep....\n");
    sleep(20);
 
    pthread_exit(NULL);
}

[Separação de tópicos: pthread_detach]

  • Se o encadeamento não for separado: o status de encerramento do encadeamento será mantido até que outro encadeamento chame pthread_join no encadeamento para obter seu status de encerramento, o status de encerramento não será liberado
  • Se o encadeamento foi desanexado: os recursos de armazenamento subjacentes do encadeamento podem ser recuperados imediatamente quando o encadeamento termina
  • Depois que o encadeamento é desanexado, não podemos usar a função pthread_join para aguardar seu estado de término, porque chamar pthread_join no encadeamento no estado desanexado produzirá um comportamento indefinido
#include <pthread.h>
int pthread_detach(pthread_t tid);
  • Valor de retorno: retorna 0 se for bem sucedido; caso contrário, retorna o número do erro 
  • Função: usado para separar threads
  • Parâmetros: o tid do fio a ser destacado

[Exclusão mútua: pthread_mutex_t]

  • O mutex é essencialmente um bloqueio. O mutex é definido (bloqueado) antes de acessar recursos compartilhados e o mutex é liberado (desbloqueado) após o acesso ser concluído
  • Inicialização e liberação de variáveis ​​mutuamente exclusivas
  • ① Inicialização estática
    • Defina a variável mutex pthread_mutex_t diretamente para a constante PTHREAD_MUTEX_INITIALIZER
    • Variáveis ​​mutex inicializadas estaticamente podem ter apenas os atributos mutex padrão e não podem definir outros atributos mutex
pthread_mutex_t  mutex;
mutex=PTHREAD_MUTEX_INITIALIZER;
//或者
pthread_mutex_t *mutex=(pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
*mutex=PTHREAD_MUTEX_INITIALIZER;
  • ② Inicialização dinâmica
    • Variáveis ​​mutex inicializadas estaticamente podem ter apenas os atributos mutex padrão, podemos inicializar dinamicamente o mutex através da função pthread_mutex_init, e você pode escolher definir os atributos mutex durante a inicialização
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
  • Valor de retorno: retorna 0 se bem-sucedido, caso contrário, retorna um número de erro
  • p th read_mutex_init :
    • Função: inicializar o mutex
    • parâmetro:
      • Parâmetro 1: o mutex precisa ser inicializado
      • Parâmetro 2: as propriedades do mutex durante a inicialização. Se você usar os atributos padrão, preencha NULL aqui
  • pthread_mutex_destroy :
    • Função: Desinicialização do mutex
    • Parâmetros: Mutex
    • Comentários (ênfase): Esta função apenas desinicializa o mutex e não libera o espaço de memória. Se o mutex for solicitado por meio de uma função como malloc, você precisará chamar a função pthread_mutex_destroy antes de liberar o mutex
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL); 
/*do something*/
pthread_mutex_destroy(&mutex);

pthread_mutex_t* mutex=(pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutex, NULL);
/*do something*/
pthread_mutex_destroy(mutex);
free(mutex);

[Bloqueio e desbloqueio de mutex]

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);  //对互斥量进行加锁。如果互斥量已经上锁,调用线程将阻塞到互斥量被解锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);  //对互斥量进行解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex); 
  • Tente bloquear o mutex (sem bloqueio). Se o mutex estiver em um estado desbloqueado, então pthead_mutex_trylock irá bloquear o mutex; se o bloqueio estiver em um estado bloqueado, então pthead_mutex_trylock retornará EBUSY em erro e não bloqueará

[Caso de contagem de referência]

struct foo {
    int f_count;
    pthread_mutex_t f_lock;
    int f_id;
};
 
struct foo *foo_alloc(int id)
{
    struct foo *fp;
 
    if ((fp == malloc(sizeof(struct foo))) != NULL) {
        fp->f_count = 1;
        fp->f_id = id;
        if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
            free(fp);
            fp = NULL;
        }
    }
 
    return fp;
}
 
void foo_hold(struct foo *fp)
{
    pthread_mutex_lock(&fp->f_lock);
    fp->f_count++;
    pthread_mutex_unlock(&fp->f_lock);
}
 
void foo_rele(struct foo *fp)
{
    pthread_mutex_lock(&fp->f_lock);
    if (--fp->f_count == 0) {
        pthread_mutex_unlock(&fp->f_lock);
        pthread_mutex_destory(&fp->f_lock);
        free(fp);
    } else {
        pthread_mutex_unlock(&fp->f_lock);
    }
}

[Timeout mutex: pthread_mutex_timedlock]

#include <pthread.h>
#include <time.h>
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict tsptr);
  • Valor de retorno: retorna 0 em caso de sucesso, caso contrário, retorna um número de erro.
  • Função: Quando um thread tenta adquirir um mutex bloqueado, pthread_mutex_timedlock permite o tempo de bloqueio do thread de ligação
  • parâmetro:
    • mutex: o mutex para tentar bloquear
    • tsptr: definir tempo limite
  • Características: Quando o valor de tempo limite for atingido, se o mutex não puder ser bloqueado com sucesso, o código de erro ETIMEDOUT será retornado
  • Nota sobre hora extra: hora extra especifica o tempo absoluto que está disposto a esperar. Este valor de tempo é um número absoluto em vez de um número relativo.
  • Por exemplo, se você está disposto a esperar 3 minutos, em vez de converter 3 minutos em uma estrutura de especificação de tempo e passá-lo para o parâmetro 2, você precisa adicionar 3 minutos à hora atual e, em seguida, convertê-la em uma estrutura de especificação de tempo e depois passá-la para o parâmetro 2.

[Pthread_mutex_timedlock evita casos de bloqueio permanente]

#include <pthread.h>
 
int main(void)
{
    int err;
    struct timespec tout;
    struct tm *tmp;
    char buf[64];
 
    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_lock(&lock);
    printf("mutex is locked\n");
	
    clock_gettime(CLOCK_REALTIME, &tout);
	
    tmp = localtime(&tout.tv_sec);
    strftime(buf, sizeof(buf), "%r", tmp);
    printf("current time is %s\n", buf);
	
    tout.tv_sec += 10; /* 10 seconds from now */
    
    /* caution: this could lead to deadlock */
    err = pthread_mutex_timedlock(&lock, &tout);
	
    clock_gettime(CLOCK_REALTIME, &tout);
    tmp = localtime(&tout.tv_sec);
    strftime(buf, sizeof(buf), "%r", tmp);
    printf("the time is now %s\n", buf);
	
    if (err == 0)
        printf("mutex locked again!\n");
    else
        printf("can’t lock mutex again: %s\n", strerror(err));
    exit(0);
}
  • Este programa bloqueia deliberadamente seu mutex existente para demonstrar como funciona o pthread_mutex_timedlock. Não é recomendado usar este método na prática, porque levará a um impasse
  • Observação: o tempo de bloqueio pode ser diferente. Há muitos motivos para diferentes motivos: o tempo de início pode ser no meio de um determinado segundo, a precisão do relógio do sistema pode não ser precisa o suficiente para suportar o valor de tempo limite especificado por nós, ou o programa continua. Antes da execução, o atraso na programação pode aumentar o valor do tempo

[Variável de condição: pthread_cond_t]

  • Variáveis ​​de condição são outro mecanismo de sincronização disponível para threads
  • Variáveis ​​de condição fornecem um ponto de encontro para vários tópicos
  • Quando variáveis ​​de condição e mutex são usados ​​juntos, os encadeamentos podem esperar que condições específicas ocorram de maneira não competitiva
  • Variáveis ​​de condição são coisas na thread, ou seja, esperando que uma determinada condição ocorra, assim como um sinal
  • A variável de condição deve ser usada com o mutex, e a própria condição é protegida pelo mutex. O thread deve primeiro bloquear o mutex antes de alterar o estado da condição
  • Outros threads não saberão dessa mudança antes de obter o mutex, porque o mutex deve ser bloqueado antes que a condição possa ser calculada
  • ① Inicialização estática
    • Defina diretamente a variável de condição definida por pthread_cond_t para a constante PTHREAD_COND_INITIALIZER
    • Variáveis ​​de condição inicializadas estaticamente podem ter apenas atributos de variáveis ​​de condição padrão e não podem definir outros atributos de variáveis ​​de condição
pthread_cond_t cond;
cond=PTHREAD_COND_INITIALIZER;
//或者
pthread_cond_t *cond=(pthread_cond_t *)malloc(sizeof(pthread_cond_t));
*cond=PTHREAD_COND_INITIALIZER;
  • ② Inicialização dinâmica
    • Variáveis ​​de condição inicializadas estaticamente só podem ter atributos de variáveis ​​de condição padrão, podemos inicializar dinamicamente as variáveis ​​de condição por meio da função pthread_mutex_init e podemos escolher definir os atributos da variável de condição durante a inicialização
#include <pthread.h>
int pthread_cond_init(pthread_cond_t* restrict cond,const pthread_condattr_t* restrict attr);
int pthread_cond_destroy(pthread_cond_t* cond);
  • Valor de retorno: retornar 0 em caso de sucesso; retornar o número do erro em caso de falha
  • pthread_cond_init :
    • Função: inicializar a variável de condição
    • parâmetro:
      • Parâmetro 1: a variável de condição que precisa ser inicializada
      • Parâmetro 2: O atributo da variável de condição durante a inicialização. Se você usar os atributos padrão, preencha NULL aqui
  • pthread_cond_destroy :
    • Função: Desinicialize a variável de condição (antes que a variável de condição libere a memória)
    • Parâmetros: variáveis ​​de condição
    • Comentários (ênfase): Esta função apenas desinicializa o mutex e não libera o espaço de memória. Se o mutex for solicitado por meio de uma função como malloc, você precisará chamar a função pthread_mutex_destroy antes de liberar o mutex
pthread_cond_t cond;
pthread_cond_init(&cond,NULL);
/*do something*/
pthread_cond_destroy(&cond);

pthread_cond_t * cond=(pthread_cond_t *)malloc(sizeof(pthread_cond_t));
pthread_cond_init(cond,NULL);
/*do something*/
pthread_cond_destroy(cond);
free(cond);

[Aguarde a função de variável de condição]

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t* restrict cond,pthread_mutex_t* restrict mutex);
int pthread_cond_timedwait(pthread_cond_t* cond,pthread_mutex_t* restrict mutex,const struct timespec* restrict tsptr);
  • Valor de retorno: retornar 0 em caso de sucesso; retornar o número do erro em caso de falha
  • Quando essas duas chamadas de função retornam com sucesso, o thread precisa recalcular a condição, porque outro thread pode já estar em execução e alterar a condição
  • pthread_cond_wait
    • Nota: Espere até que a variável de condição se torne verdadeira
    • Como usar: O parâmetro mutex mutex é bloqueado antecipadamente, e então o mutex protege a condição, esperando que a variável de condição do parâmetro 1cond se torne verdadeira. No processo de espera que a variável de condição se torne verdadeira, esta função foi bloqueada. Mas quando em um estado de bloqueio, o mutex mutex é desbloqueado (porque outros threads precisam usar esse bloqueio para tornar a variável de condição verdadeira)
    • Quando a função pthread_cond_wait retorna, o mutex é bloqueado novamente
  • pthread_cond_timedwait
    • A função pthread_cond_timedwait tem a mesma função que a função pthread_cond_wait. Mas há mais um parâmetro de tempo limite. O valor do tempo limite especifica quanto tempo estamos dispostos a esperar, que é representado pela estrutura de timespec
    • Se a condição não aparecer após o tempo limite expirar, esta função irá recuperar o mutex e retornar o erro ETIMEOUT
    • Nota: este valor de tempo é um número absoluto e não um número relativo. Por exemplo, se você deseja esperar 3 minutos, em vez de converter 3 minutos em uma estrutura de especificação de tempo, você precisa adicionar 3 minutos ao horário atual e então convertê-lo em uma estrutura de especificação de tempo

[Obtenha a função de aquisição de tempo absoluto do valor de tempo limite]

  • Você pode usar a função clock_gettime para obter a hora atual representada pela estrutura timespec. Mas nem todas as plataformas atualmente oferecem suporte a essa função. Portanto, você pode usar gettimeofday para obter a hora atual representada pela estrutura timeval e, em seguida, converter essa hora em uma estrutura de especificação de tempo
#include <sys/time.h>
#include <stdlib.h>
 
void maketimeout(struct timespec *tsp, long minutes)
{
	struct timeval now;
 
	/* get the current time */
	gettimeofday(&now, NULL);
	
	tsp->tv_sec = now.tv_sec;
	tsp->tv_nsec = now.tv_usec * 1000; /* usec to nsec */
	/* add the offset to get timeout value */
	tsp->tv_sec += minutes * 60;
}

【Função de envio de sinal variável de condição】

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t* cond);    //至少能唤醒一个等待该条件的线程
int pthread_cond_broadcast(pthread_cond_t* cond); //唤醒等待该条件的所有线程
  • Valor de retorno: retornar 0 em caso de sucesso; retornar o número do erro em caso de falha
  • Essas duas funções são usadas para notificar a thread de que a variável de condição atendeu à condição (torna-se verdadeira). Quando essas duas funções são chamadas, elas estão sinalizando o thread ou condição
  • Atenção deve ser dada: o thread deve ser sinalizado após alterar o estado de condição

[Combine o uso de variáveis ​​de condição e mutex para sincronizar threads]

#include <pthread.h>
 
struct msg {
	struct msg *m_next;
	/* ... more stuff here ... */
};
 
struct msg  *workq;
pthread_cond_t  qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
 
void  process_msg(void)
{
	struct msg *mp;
 
	for (;;) {
		pthread_mutex_lock(&qlock);
		while (workq == NULL)
			pthread_cond_wait(&qready, &qlock);
		mp = workq;
		workq = mp->m_next;
		pthread_mutex_unlock(&qlock);
		/* now process the message mp */
	}
}

void  enqueue_msg(struct msg *mp)
{
	pthread_mutex_lock(&qlock);
	mp->m_next = workq;
	workq = mp;
	pthread_mutex_unlock(&qlock);
	pthread_cond_signal(&qready);
}

 

Acho que você gosta

Origin blog.csdn.net/baidu_41388533/article/details/114851779
Recomendado
Clasificación