1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

C e Linux..... threads - operação atómica!

Discussão em 'Programação' iniciada por toblesu, 15 de Julho de 2008. (Respostas: 26; Visualizações: 2912)

  1. toblesu

    toblesu Power Member

    Boas Pessoal,


    Estou a fazer um projecto do tipo Cliente-Servidor. Precisava de uma função que fizesse com que a execução de uma thread nunca fosse interrompida pelo escalonador, isto é, a thread é executada na sua totalidade, sendo que o CPU não pode ser atribuido a outra até ao seu término (isto porque preciso de fazer com que determinada operação seja atómica!!)

    o sistema é um sistem de transacções bancárias, e o problema prende-se nas transfências!!

    Se me puderem ajudar!! Agradecia muito!


    :)
     
  2. hYpe

    hYpe [email protected] Member

    Hmm..

    Em vez de uma thread, porque não usas um processo, pondo o filho a fazer essa tal tarefa, e o pai à espera que o filho termine?

    Assim garantes que ele só continua depois da operação "atómica" (achei piada ao nome) ter terminado.
     
  3. toblesu

    toblesu Power Member

    isto tem msm que ser feito com threads... nao pode ser com processos!! requisitos do trabalho..... :S

    o conceito de atómico, está relaciona com o término da operação.. isto é, a thread nao pode ser interrompida pelo escalonador (espero nao estar a cometer nenhuma gaffe... mas pelo que percebi do que me foi transmitido é mais ou menos isto!) para dar lugar a outra thread...
    trata-se de um sistema client/multithreaded server....

    nao percebo muito disto...
     
    Última edição: 15 de Julho de 2008
  4. hYpe

    hYpe [email protected] Member

    Não sei até que ponto isso é possível.

    Repara que para o próprio sistema operativo estar a correr, há processos prioritários a correr (para ler do teclado, para mexeres o rato, para detectar inputs, para teres imagem no ecra, para teres rede, para teres wireless, etc etc etc etc)...

    Portanto não sei até que ponto consegues fazer isso. Quanto muito consegues simular isso através de mutex's.
     
  5. toblesu

    toblesu Power Member

    estou a utilizar mutexs..... (aí também reside uma grande questão minha, porque é um mutex geral.. e o ideal seria um mutex por cliente, mas também nao sei como fazer isso!!), mas o professor disse que para que a operação se tornasse atómica tinha que ser passada à funcão de inicio da thread um ptrhead_(qualquer coisa), de modo que tornasse a thread interrompivel....

    :S
     
  6. hYpe

    hYpe [email protected] Member

    Podes usar um vector de mutex's.. Assim tens um para cada cliente que entra.

    Para controlar qual o mutex de cada cliente, nada como atribuir um ID unico a cada cliente que entra... Sendo esse numero protegido por um único mutex.

    Eu nunca usei threads atómicas.. Mas fiquei curioso quanto à sua existência. Se descobrires como funciona, dá uma apitadela neste tópico!
     
  7. toblesu

    toblesu Power Member

    ok!! avisarei quando tiver a solução para isso... se conseguir obter antes do fim de semana.... tenho um deadline apertado.. mas vou tentar!!

    será que me podes dar um exemplo de array de mutex's.. nao consigo visualizar muito bem.. ou melhor acho que consigo.. mas parece-me que aquilo que estou a visualizar nao vai dar grandes resultados!!!

    poderia por exemplo ser do género:

    Código:
    array_mutex[MAX_CLIENTES]; //declaracao
    
    pthread_mutex_t mutex_control = PTHREAD_MUTEX_INITIALIZER; 
    
    array_mutex[id_cliente]=mutex_control;

    confesso sinceramente que nao sei mesmo se isto está alguma coisa de jeito, quanto mais alguma coisa correcto... tenho estado a usar um mutex para todos os clientes, e quando ele é aplicado bloqueia todos os outros.... sei que nao é o mais correcto (de longe!!)... mas nao sei como fazer!!

    se me puderes esclarecer!! ;) agradecia!!!
     
    Última edição pelo moderador: 15 de Julho de 2008
  8. Dragon_Tamer

    Dragon_Tamer Power Member

    Uma técnica que podes usar, é a de colocar todas as threads em pause() , excepto a dita a que queres dar prioridade. Quando essa terminar a execução desse segmento de código que queres dar prioridade, ela envia um sinal para a thread main em ordem para continuar com a execução normal do programa.

    Ou então se essa thread terminar logo acabe esse código, usas simplesmente o pthread_join, na main thread.
    Dessa maneira a main thread fica em suspensão até essa terminar o que tem a fazer.
     
  9. toblesu

    toblesu Power Member

    nao sei se percebi muito bem....

    a thread so vai terminar quanto o cliente fizer logout... ou entao por qq outro motivo vindo do lado do servidor, caso do timeout......

    usando o pause(), como poderia fazer isso??
    do tipo, no ciclo for, percorrer todas as threads criadas e para cada thread comparar com a thread do cliente loggado, se a thread for diferente, associo-lhe um pause(), é isso??

    do tipo,

    Código:
    for(i=0; i<=MAX_LIGACOES; i++){
             if(thread[i]!=id_cliente)
                   pause();
    }
    ??? [este pode nao se o melhor exemplo, mas se me indicarem que o raciocinio nao está de todo incorrecto, conseguirei adptar ao meu código!].

    será nesta linha?? isto garantirá então a tal atomicidade da operação??
    e no final da thread terminar a sua função, será preciso "retirar" as outras threads do pause?? ou isso é feito automaticamente??

    obrigado pela ajuda!!
     
    Última edição pelo moderador: 15 de Julho de 2008
  10. souto

    souto To fold or to FOLD?

    É impossível ditares ao sistema operativo para não escalonar a CPU durante o tempo de execução dessa thread...
    A única coisa que podes garantir é a atomicidade da operação dentro do processo em si, através do uso de mutexes ou outro mecanismo qualquer...

    Boa sorte.
     
  11. toblesu

    toblesu Power Member

    hummm entendo.. e foi falha minha..... porque ja estou a utilizar mutexs! (poucos dominio dá nisto! :S)

    já agora se me puderem dar uma opinião como se criam array's de mutexs, de modo associar um mutex a cada cliente!

    o meu raciocinio uns posts acima está correcto???

    obrigadao pela ajuda e esclarecimentos!! :)
     
  12. hYpe

    hYpe [email protected] Member

    Acho que assim dá.. Já não trabalho com isto há uns meses largos... Normalmente uso processos, semaforos, etc.
     
  13. Dragon_Tamer

    Dragon_Tamer Power Member

    Se o teu objectivo é criar uma zona de exclusão mútua para todas as threads, então só deverás precisar de um mutex.
    Quando uma thread chega a essa secção do código, ela vai tentar adquirir o mutex. Se o mutex estiver disponivel, adquirio tornando indisponível para as outras de o obter. Senão tem de esperar que a thread que tem o mutex acabe de processar o código, para que no final o mutex seja libertado e possa ser adiquirido por outra. Criando assim uma zona de exclusão mútua que creio que é isso que tu queres.
    Se o objectivo é parar todas as threads quando certa parte do código está a ser processado, aí já terás de trabalhar com sinais e pauses para aí.

    Se precisares de fichas resolvidas que envolvam mutexes e afins, manda p.m. ou alguma coisa para eu te enviar.
     
    Última edição: 15 de Julho de 2008
  14. toblesu

    toblesu Power Member

    O objectivo, é garantir que a operação transferências consiga ser efectuada no seu todo sem interrupção...
    isto é o cliente tem que debitar a sua conta e creditar a conta de outro, escrever em dois ficheiros.... preciso de garantir que aquela parte do código nao pode ser interrompida enquanto decorrer a operação... quando o cliente está a creditar a conta do outro (escrever quer no ficheiro quer actualizar o valor na memória) tenho que garantir que o cliente que está a receber a transferencia (se estiver a efectuar uma operção de levantamento ou deposito ou outra coisa qualquer) nao pode estar a escrever no ficheiro ao mesmo tempo ou aceder á mesma zona de memória onde o valor da transferencia vai ser colocado!

    nao sei se me fiz entender!
    ah! e existe uma thread para cada cliente, para tratar de todos os pedidos do cliente.

    o uso de mutexs poder-me-ia garantir a atomicidade dessa operação?? ou o mutex nao é suficiente para esta situação??

    Se calhar, neste caso nao fará muito sentido parar todas as threads, visto nao ser uma thread para cada pedido, antes uma thread para tratar todos os pedidos dos clientes, e no momento daquela operação, as outras threads poderao estar ocupadas com outro tipo de operação que nao seja transferência!


    se calhar posso estar a fazer grande confusão....
     
    Última edição: 16 de Julho de 2008
  15. Dragon_Tamer

    Dragon_Tamer Power Member

    Ok, se é para aceder em ficheiros em exclusão mútua então creio que é melhor mutexes na parte de acesso aos ficheiros.
    Mas atenção: com o programa assim, enquanto um cliente faz uma operação, os outros podem fazê-la mas o registo de cada um só é feito quando a sua thread conseguir adquirir o/s mutex/s.
    Como cada cliente vai ter o seu ficheiro com dados, deverá ser um mutex para cada um, para não parar os restantes clientes quando eles estão a realizar uma operação que não esteja relacionada com os 2 primeiros.

    Podes ir a este link sacar o pdf, se estás com dúvidas: https://www.dei.uc.pt/weboncampus/getFile.do?tipo=2&id=5045

    Eu pessoalmente já não tenho isso desde o ano passado por isso já não está muito fresco na memória, mas dá uma vista de olhos.
     
  16. The_True_Eue

    The_True_Eue Power Member

    Isso pode ser feito de várias maneiras, mas todas com o mesmo princípio por trás.
    Ao que parece precisas de vários mutexes, um para cada ficheiro, certo?
    Pois podes simplesmente fazer isso: criar um mutex para cada ficheiro, e cada thread adquire o(s) mutex(es) que necessita. Precisas então de uma forma de indexar os mutexes pelo nome do ficheiro correspondente. Vêm-me à memória hash tables, mas dependendo da forma como referencias os ficheiros dos clientes podem existir soluções mais simples.
    Esta solução acarreta o problema de usar toneladas de mutexes, o que pode não ser desejável.
    --
    Se for esse o caso, podes usar apenas um só mutex mais uma lista de ficheiros em uso. Quando uma thread quiser accesso a um ou mais ficheiros pede o único mutex que existe. Quando finalmente o obtiver, verifica se o(s) ficheiro(s) que deseja está(ão) em uso. Se não estiverem, adquire-os e liberta o mutex. Se estiverem em uso, coloca-se na fila de espera desse ficheiro e liberta o mutex. O objectivo é que apenas uma thread de cada vez mexa na lista de ficheiros em uso. Quando uma thread termina o trabalho com um ficheiro, adquire o mutex, actualiza a lista de ficheiros, faz avançar a fila e liberta o mutex.
    --
    A primeira solução tem um outro problema. Se uma thread necessita do ficheiro A e B, e outra do ficheiro B e A, pode acontecer da primeira bloquear à espera do B e a segunda bloquear à espera do A. Um deadlock. A solução é semelhante à segunda. Cria-se um mutex que serve para adquirir mutexes. Assim uma thread pode adquirir vários ficheiros como uma única operação.
    --
    Espero que tenha ajudado, e não complicado mais as coisas... Às vezes faço isso...
    Também posso ter cometido várias calinadas pelo caminho, porque sou um autodidacta em sincronização.
     
  17. _jr

    _jr Power Member

    A resposta já foi dada, isto é tão simples quanto colocar todo o bloco de código destas operações dentro de uma CRITICAL_SECTION (mutex, semaforo binário...como queiram chamar).


    Código:
    #include <pthread.h>
    pthread_mutex_t cs_mutex = PTHREAD_MUTEX_INITIALIZER;
    
    pthread_mutex_lock( &cs_mutex );
    
       // ..codigo protegido...
    
    pthread_mutex_unlock( &cs_mutex );
    Tens que ter atenção em uma coisa, o mutex (no exemplo cs_mutex) tem que ser global e exportado ou passado por referencia para dentro das threads e todas tem que usar este mutex no pthread_mutex_lock().


    De certeza que teu prof de SO esta a pedir isso...
     
    Última edição pelo moderador: 16 de Julho de 2008
  18. toblesu

    toblesu Power Member

    De facto estou a utilizar essa situação que descreves, tendo essa especial atenção de passar por referencia.

    o meu problema começou quando me falaram em array's de mutexs, em atribuir um mutex para cada cliente.....

    porque pensava que a solução adoptada seria suficiente, mas como nao domino, nem de longe nem de perto a temática, fiquei com sérias duvidas quanto a esta questão.

    obrigado a todos pela ajuda e esclarecimentos prestados!

    ;)
     
  19. Dragon_Tamer

    Dragon_Tamer Power Member

    De nada :)

    (Desculpem o spam, mas não resisti :P)
     
  20. toblesu

    toblesu Power Member

    Sendo ainda um pouco mais persistente no assunto....

    nao consigo ainda perceber como se cria array's de mutexs (portanto, criar um mutex para cada cliente)... e na altura de A bloquear o acesso de B aquela zona de código (na transferência, escrita no ficheiro e na memória), em vez de também bloquear C, D, E...... (que nada têm a ver com a transacção) - como está feito com o uso de um mutex geral - como se procede a essa situação?

    Obrigado..
     

Partilhar esta Página