concorrência

Propaganda
Linguagens Concorrentes
Antonio Francisco do Prado
[email protected]
Concorrência
Multiprogramação: usada por um sistema "timesharing". Um processador compartilhado por diversos
processos;
Multiprocessamento: vários processadores. Possibilita
que múltiplos processos sejam executados em
processadores distintos. Memória comum compartilhada
para comunicação entre os processos.
Processamento Distribuído: também requer
processadores separados, mas cada um com sua
memória. Processadores conectados via linhas de
comunicação.
Concorrência
A concorrência é naturalmente dividida em nível de:
• instrução (executando duas ou mais instruções de
máquina simultaneamente);
• comando (executando dois ou mais comandos
simultaneamente); e
• unidade (executando dois ou mais programas
simultaneamente).
Os métodos concorrentes aumentam a flexibilidade
de programação e foram criados originalmente
para serem usados em problemas particulares dos
em sistemas operacionais.
Concorrência
Concorrência relaciona-se com fluxo de controle de um
programa. Tem-se mais de um fluxo de controle ativo. É
diferente da execução seqüencial de programas, onde se
tem apenas um fluxo de controle, ou seja, em um
determinado momento, existe uma única instrução
candidata à execução.
Unidades concorrentes podem ser executadas em:
• Um único processador ;
• Vários processadores que compartilham uma
memória;
• Vários processadores independentes, sem
compartilhamento de memória.
Concorrência
• Reduz o tempo total de processamento através de
execução concorrente de diversas unidades;
• Aumenta a confiabilidade para aplicações críticas,
onde não se torna confiável a execução em um único
processador;
• Modela soluções que exploram a capacidade de
máquinas com múltiplos processadores;
• Implementa aplicações distribuídas.
Conceitos básicos
Seção crítica
Quando processos concorrentes interagem com
variáveis compartilhadas, a integridade destas variáveis
pode ser violada se o acesso não for coordenado. Uma
seção crítica é um segmento de código de um processo
que acessa um recurso compartilhado.
Deadlock
É uma situação onde um processo ou um conjunto de
processos estão bloqueados, a espera de um evento
que nunca irá acontecer.
Conceitos básicos
Deadlock
•Um deadlock é caracterizado por uma espera circular
•Exemplo: o processo P1 está de posse do recurso r1 , e
precisa do recurso r2; o processo P2 está de posse de r2
e precisa de r1; Nesse caso, nenhum dos processos
pode prosseguir, pois ambos dependem de recursos que
não serão liberados.
P1
P2
r1
r2
Mecanismos
de Sincronização
Semáforos
O conceito de semáforos consiste na colocação de
proteções (guardas) no código que controlam o acesso a
uma estrutura de dados. Em geral, a estrutura é uma fila,
funcionando em regime FiFo(First in First out).
A implementação do semáforo deve garantir que, uma
vez que um processo inicie uma operação sobre um
semáforo, nenhum outro processo terá acesso até que a
operação conclua.
Conceitos básicos
Tarefa
Uma tarefa é uma unidade de um programa que pode
estar em execução concorrente com outras unidades do
mesmo programa . Uma tarefa pode comunicar-se com
outras tarefas através variáveis não-locais
compartilhadas, mensagens ou de parâmetros.
As tarefas disjuntas ocorrem, se uma tarefa não se
comunicar ou não afetar a execução de qualquer outra
tarefa. Devem de alguma forma se comunicar para que
haja sincronização em suas execuções, no
compartilhamento de dados.
Conceitos básicos
Tarefa
tarefa1
tarefa2
Unidade concorrente
Tarefa n
Conceitos básicos
Sincronização de tarefas
Sincronização é um mecanismo que controla a ordem de
execução das tarefas.
Cooperação
A cooperação entre processos revela-se quando um
processo aguarda que outro processo realize alguma
tarefa, para prosseguir sua execução.
Assim a cooperação entre as tarefas A e B ocorre,
quando B precisa aguardar que A conclua alguma
atividade específica antes de prosseguir sua execução.
Conceitos básicos
Competição
Ocorre quando ambas tarefas requerem algum recurso
que não pode ser usado simultaneamente. Assim, se a
tarefa A precisa acessar um dado compartilhado x que
já esta sendo acessado pela tarefa B, a tarefa A precisa
aguardar que B conclua seu acesso a x.
Conceitos básicos
Competição
Tarefa T1
Unidade
Concorrente
Tarefa T2
Enquanto T1 estiver acessando, T2 tem que esperar
Conceitos básicos
Exclusão mútua
A Exclusão Mútua ou, simplesmente, Mutex,
é um caso particular competição por recurso, onde apenas se pode permitir o
acesso individual ao recurso(regiões críticas).Os primeiros mecanismos da
exclusão mútua faziam com que os processos testassem continuamente o valor
de uma variável que guarda o estado do recurso, até sua liberação, podendo
causar um Deadlock.
Jantar dos filósofos
•Os filosofos tentam
comer e para isso
dependem do recurso
(palito). Para comer
os filósofos precisam de
dois palitos.
Caso um filosofo
não esteja comendo,
pode estar pensando ou
dormindo.
Conceitos básicos
Para que a competição por um recurso decorra sem
qualquer problema são, normalmente, usados
semáforos que permitem, ou não, o acesso de um ou
mais processos à região crítica.
Outros mecanismo de sincronização :
• Monitores; e
•Passagem de mensagem(rendezvous).
Comportamento da comunicação entre tarefas:
• Síncrono
• Assíncrono
Mecanismos
de Sincronização
Monitores
Os monitores podem ser utilizados como uma solução
em ambiente concorrente transformando as estruturas
de dados compartilhados em Tipos Abstratos de Dados,
que agrupam as estruturas de dados com suas
operações, e ocultam suas representações. Os
monitores implementam a exclusão mútua, onde
somente um processo pode estar ativo dentro do monitor
em um instante de tempo.
Mecanismos
de Sincronização
Monitores (continuação)
Quando um processo chama um método de um monitor,
as primeiras instruções do método verificam se algum
outro processo está ativo dentro dele. Se isto for
verdade, o processo que chamou o método do monitor
será suspenso até que o outro processo deixe o monitor.
Se não houver nenhum processo ativo dentro do monitor,
o processo poderá entrar e executar o método chamado.
Mecanismos
de Sincronização
Monitores
Processos
aguardando entrada
Mecanismos
de Sincronização
Passagem de mensagem
A construção de monitores não moldam a sincronização
em sistemas distribuídos, onde seria necessário a
sincronização de unidades, na qual cada processador
teria sua própria memória, em vez de uma única
memória compartilhada.
Para sincronizar os processos independentes é comum
a utilização de monitores. Contudo, ao utilizarmos
sistemas sem memória comum e com mais de um
processador, a implementação dos monitores se torna
inviável, porque não existe nenhum meio físico central.
Surge assim uma técnica de encontros para tratar estes
casos, que se faz através de mensagens.
Mecanismos
de Sincronização
rendezvous
Uma tarefa pode ser projetada de modo a poder
suspender sua execução em certo ponto, porque está
ociosa ou porque precisa de informações de outra
unidade antes que possa prosseguir. Se uma tarefa A
quer enviar uma mensagem para a tarefa B, e se esta
estiver disposta a receber, a mensagem poderá ser
transmitida. Essa transmissão é chamada rendezvous.
Mecanismos
de Sincronização
Passagem de mensagem (Rendezvous)
Tarefa 1
Tarefa 2
Requisição
Processo
Bloqueado
Confirmação
Resposta
Confirmação
Processo
Contínuo
Processo
Contínuo
Linguagens Concorrentes
Java
(Multilinhas)
Multilinhas e Sincronização


Multitarefas x Multilinhas

Multitarefas - estão em espaço
de endereçamento distinto e
devem ser vistos como
programas diferentes no
mesmo sistema.

Multilinhas - compartilham o
mesmo espaço de
endereçamento e dividem
cooperativamente o mesmo
processo.
O modelo de Linhas de Execução
de Java

Java usa multilinhas de
execução para permitir que
todo o ambiente Java seja
assíncrono. Não há um laço
principal em um programa
Java. Cada linha tem sua
execução independente.

Uma linha bloqueada não
impede a execução das
demais linhas.

Sincronização
A sincronização de
recursos requeridos pelas
linhas, executadas de forma
assíncrona, é obtida pelo
mecanismo Monitor. Em
Java, não há uma classe
monitor. Cada objeto tem
seu próprio monitor, com
seus métodos sincronizados.
Quando uma linha está
executando um método
sincronizado, nenhuma outra
linha pode executar este
método.
Thread
 Para criar programas
concorrentes em Java
reutiliza-se a classe
Thread.
 A classe Thread
encapsula todos os
controles das linhas de
execução. Um objeto
Thread é o procurador de
uma linha em execução.
 Quando um programa
Java é iniciado já existe
uma linha sendo
executada. O programa
principal de java é uma
linha em execução.
class ThreadCorrente {
public static void main(String args[ ]){
Thread t = Thread.currentThread( );
t.setName("Minha Linha");
System.out.println("Linha corrente: " + t);
try{
for (int n = 5; n > 0; n --) {
System.out.println ( " " + n);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("interrompida");
} //fim do main
}
Resultado da execução 
Linha corrente: Thread [ Minha Linha,5,main ]
5
4
3
2
1
}
Java – Concorrência
Classe Thread
notify
notifyAll
criado
start
Acorda
pronto
run
resume
yield
executando
wait
esperando
sleep
adormecido
suspend
Completo
(destroy)
morto
bloqueado
Threads Java
Principais métodos
sleep: passa como parâmetro um número inteiro de
milissegundos que a thread deve permanecer
interrompida;
suspend: interrompe temporariamente a thread, que
pode ser reiniciada posteriormente;
resume: reinicia a thread;
yield: passa o controle para outra thread;
syncronized: faz com que um recurso seja acessado
atomicamente;
notify: libera um recurso sincronizado para a próxima
thread;
notifyAll: libera um recurso sincronizado para todas as
threads; e
wait: aguarda pela liberação de um recurso
sincronizado.
Java – Concorrência
A sincronização de competição em Java é obtida
especificando-se os métodos sincronizados que
acessam dados compartilhados. A execução destes
métodos deve ser concluída para que outra thread
execute-os novamente. Cada método sincronizado
coloca um bloqueio no objeto, que impede que outros
métodos sejam executados sobre este objeto. Usa o
modificador synchronized na definição do método.

A entrada em um monitor de objetos, é feita pela chamada de um
método marcado com synchronized.
synchronized void metodo() {
Sincronização
<HTML>
<HEAD>
<TITLE>Autogenerated HTML</TITLE>
</HEAD>
<BODY>
<APPLET CODE="Applet1.class"
WIDTH=426 HEIGHT=266></APPLET>
</BODY>
</HTML>
roda.html
Sincronização
import java.awt.*;
class Chamado{
synchronized void Chama(String msg) {
Applet1.ShowMessage(msg);
//try {Thread.sleep(1000);}
try { Thread.sleep((int)Math.random()*1000); }
catch(Exception e){ }
Applet1.ShowMessage(msg);
}
}
class Chamador implements Runnable {
String msg;
Chamado alvo;
public Chamador(Chamado c, String s){
alvo = c;
msg = s;
new Thread(this).start();
}
public void run(){
alvo.Chama(msg);
}
}
import java.applet.*;
Sincronização
public class Applet1 extends Applet
{
public void init() {
setLayout(null);
setSize(426,266);
button1 = new java.awt.Button();
button1.setLabel("Executar!");
button1.setBounds(324,72,66,94);
button1.setBackground(new Color(12632256));
add(button1);
list1 = new java.awt.List(4);
add(list1);
list1.setBounds(12,60,276,140);
Acoes aAcoes = new Acoes();
button1.addMouseListener(aAcoes);
}
java.awt.Button button1;
static java.awt.List list1;
class Acoes extends java.awt.event.MouseAdapter
{ public void mouseClicked(java.awt.event.MouseEvent event)
{
Object object = event.getSource();
if (object == button1) executarThread(event);
}
}
Sincronização
void executarThread(java.awt.event.MouseEvent event)
{
Chamado alvo = new Chamado();
Thread corrente=Thread.currentThread();
ShowMessage(String.valueOf(corrente));
new Chamador(alvo,"Ola");
new Chamador(alvo,"Pessoal");
new Chamador(alvo,"Sincronizado");
ShowMessage("Fim criação chamador");
}
static void ShowMessage(String s)
{
list1.addItem(s);
}
}// fim da classe Applet1
Java – Concorrência
A sincronização de cooperação em Java é obtida
com os métodos wait e notify definidos em na classe
Object.
O método wait é colocado em um laço que testa a
condição de acesso a uma região crítica. Se a
condição for falsa, a thread é colocada em uma fila de
espera. O método notify é chamado para notificar uma
thread, que a região crítica está liberada. wait e notify
somente podem ser chamados de dentro de um
método sincronizado. Usam o bloqueio do objeto
realizado pelo syncronized.
Produtor e Consumidor
<HTML>
<HEAD>
<TITLE>Relogio</TITLE>
procon.html
</HEAD>
<BODY>
<P><APPLET CODE="Applet1.class"
WIDTH=“426" HEIGHT=“266" ALIGN="BOTTOM">
</APPLET>
</BODY>
</HTML>
Java – Produtor e Consumidor
class Controle{
static int n;
boolean flag1 = false;
synchronized int get() {
while(!flag1)
//if(!flag1)
try { wait(); } catch(InterruptedException e){ }
Applet1.ShowMessage("Lendo: "+ String.valueOf(n));
flag1 = false;
notify();
return n; }
synchronized void put(int n) {
while(flag1)
//if(flag1)
try { wait(); }catch(InterruptedException e){ }
this.n = n;
flag1 = true;
Applet1.ShowMessage("Colocando: "+ n);
notify(); }
}
class Produtor implements Runnable{
Controle c1;
Produtor (Controle c1) {
this.c1=c1;
new Thread(this, "Produtor").start();
}
public void run() {
int i = 0;
while(Controle.n < 10) { //while(true)
c1.put(i++); }
}
}
class Consumidor implements Runnable{
Controle c1;
Consumidor(Controle c1) {
this.c1=c1;
new Thread(this,"Consumidor").start();
}
public void run(){
while(Controle.n < 10) { //while(true)
c1.get(); }
}
}
import java.awt.*;
import java.applet.*;
public class Applet1 extends Applet
{
public void init()
{
setLayout(null);
setSize(426,266);
button1 = new java.awt.Button();
button1.setLabel("button");
button1.setBounds(264,96,116,60);
button1.setBackground(new Color(12632256));
add(button1);
list1 = new java.awt.List(4);
add(list1);
list1.setBounds(12,36,222,194);
SymMouse aSymMouse = new SymMouse();
button1.addMouseListener(aSymMouse);
}
java.awt.Button button1;
static java.awt.List list1;
class SymMouse extends java.awt.event.MouseAdapter
{
public void mouseClicked(java.awt.event.MouseEvent event)
{
Object object = event.getSource();
if (object == button1)
button1_MouseClicked(event);
}
void button1_MouseClicked(java.awt.event.MouseEvent event)
{
Controle c1 = new Controle();
new Produtor(c1);
new Consumidor(c1);
}
}
static void ShowMessage(String s)
{
list1.addItem(s);
}
}
Jantar dos filósofos
public class Palitos {
private boolean[] catched = new boolean[5];
//vetor de Palitos - True(em uso) False(liberado)
public Palitos( ) { }
public synchronized void pick2(Filosofos f){
//método para pegar os 2 Palitos (sincronizado)
Int key = f.getKey( );
//identifica o filósofo que quer pegar os Palitos
while ( catched[key] || catched[((key +1)%5)] ){
//Espera até que seu Palito ou
//o do seu vizinho à direita estiver em uso
f.setStatus(2); //passa para o estado FAMINTO
try{ wait( ); } //espera
catch(Exception e){}
}
catched[key] = true;
catched[((key +1)%5)] = true;
f.setStatus(1); //passa para o estado COMENDO
}//fim pick2
public synchronized void put2(Filosofos f){
// método para liberar os 2 Palitos usados
int key; key = f.getKey( );
//identifica o filósofo que vai liberar os Palitos
catched[key] = false; //libera o seu Palito
//e o de seu vizinho à direita
int aux = (key+1)%5;
catched[aux] = false;
try{ notifyAll( ); }
//notifica que liberou os Palitos
catch(Exception e){ }
}//fim put2
}//fim da classe Palitos
public class Jantar {
private Filosofos
f0,f1,f2,f3,f4;
public Palitos palito;
public Jantar() {
palito = new Palitos();
// cria objeto palitos
f0 = new Filosofos(0,this);
//cria threads filósofos
f1 = new Filosofos(1,this);
f2 = new Filosofos(2,this);
f3 = new Filosofos(3,this);
f4 = new Filosofos(4,this);
f0.start(); f1.start();
f2.start(); f3.start();
f4.start();
}
public static void
main(String[] args) {
new Jantar();
}
public void SetInfo(int key, int status){
if (key == 0) {
if (status ==0) {
System.out.println("0
else if (status ==1) {
System.out.println("0
else if (status ==2) {
System.out.println("0
else if (key == 1) {
if (status ==0) {
System.out.println("1
else if (status ==1) {
System.out.println("1
else if (status ==2) {
System.out.println("1
else if (key == 2) {
if (status ==0) {
System.out.println("2
else if (status ==1) {
System.out.println("2
else if (status ==2) {
System.out.println("2
else if (key == 3) {
if (status ==0) {
System.out.println("3
else if (status ==1) {
System.out.println("3
else if (status ==2) {
System.out.println("3
else if (key == 4) {
if (status ==0) {
System.out.println("4
else if (status ==1) {
System.out.println("4
else if (status ==2) {
System.out.println("4
} } }
- Pensando"); }
- Comendo"); }
- Faminto"); } }
- Pensando"); }
- Comendo"); }
- Faminto"); } }
- Pensando"); }
- Comendo"); }
- Faminto"); } }
- Pensando"); }
- Comendo"); }
- Faminto"); } }
- Pensando"); }
- Comendo"); }
- Faminto"); }
public class Filosofos extends Thread{
//cada filósofo é visto como um processo
private int key; // identifica o filósofo
private int status;
// 0 = pensa , 1 = come , 2 = faminto
private Jantar j; // objeto jantar
public Filosofos(int key,Jantar j) {
this.key = key;
this.j = j;
}
public int getKey(){ // pega identificador do filósofo
return key;
}
public void setStatus(int
status = i;
switch ( i ){
case 0 : j.SetInfo(key,
case 1 : j.SetInfo(key,
case 2 : j.SetInfo(key,
}
i){ // seta status do filósofo
0); break;
1); break;
2); break; }
private void pensando(){
// no estado pensando bloqueia
//por um certo tempo 2000ms)
try{Thread.sleep(2000);}
catch(Exception e){}
}
private void comendo(){ // no estado comendo
//bloqueia por um certo tempo (2500 ms)
try{Thread.sleep(2500);}
catch(Exception e){}
}
public void run(){
while(true){ // roda indefinidamente
setStatus(0); // filósofo pensando
pensando(); // pensa - bloqueia por certo tempo
j.palito.pick2(this); // filósofo pega os Palitos
comendo(); // come - bloqueia por certo tempo
j.palito.put2(this); // libera os Palitos }
}
}
}//fim da classe Filosofos
3 Threads relogio
<HTML>
<HEAD>
<TITLE>Relogio</TITLE>
relogio.html
</HEAD>
<BODY>
<P><APPLET CODE="Applet1.class"
WIDTH="500" HEIGHT="361" ALIGN="BOTTOM">
</APPLET>
</BODY>
</HTML>
import java.awt.*;
class relogio extends Canvas implements Runnable
{ private Thread UmaThread; // declara a thread
private Polygon UmPoligono;
private int polyX[] = new int[9], //coordenadas X
polyY[] = new int[9], //coordenadas Y
posicao,
//posicao da linha
delay = 100; // sleep em milesegundos
public relogio()
{
resize(130, 130);
DefinePoligono();
UmPoligono = new Polygon(polyX, polyY, 9);
posicao = 0;
UmaThread = new Thread(this); / cria a thread
UmaThread.start(); //inicia a thread
}
public relogio(int _delay) // construtor da classe relogio
{
this();
if(_delay < 50) delay = 50;
else if(_delay > 300) delay = 300;
else delay = _delay;
}
public void reset() {posicao = 0;}
public void resume() { UmaThread.resume(); } // resume( )
public void suspende() { UmaThread.suspend(); } // suspend ( )
public void destroy() { this.UmaThread = null; } // destroy ( )
public void run() // run do objeto Runnable, passado para a Thread
{
while (true)
{
repaint(); // chama o paint passando uma caneta gráfica
try{ Thread.sleep(delay); } // sleep ( )
catch(InterruptedException e) { this.suspende(); }
avancar();
}
}
//Desenha a linha do centro até a posição
public void paint(Graphics g)
{ // chamado pelo repaint()
g.drawPolygon(UmPoligono);
g.drawLine(65, 65, polyX[posicao], polyY[posicao]);
}
private void avancar()
{
if(posicao < 6) posicao++;
else posicao = 0;
}
//vetor com as coordenadas X e Y
polyY[0] = 1;
private void DefinePoligono()
polyY[1] = 1;
{
polyY[2] = 37;
polyX[0] = 37;
polyY[3] = 97;
polyX[1] = 97;
polyY[4] = 129;
polyX[2] = 129;
polyY[5] = 129;
polyX[3] = 129;
polyY[6] = 97;
polyX[4] = 97;
polyY[7] = 37;
polyX[5] = 37;
polyY[8] = 1;
polyX[6] = 1;
} // fim DefinePoligono
polyX[7] = 1;
}// fim da classe relogio
polyX[8] = 37;
import java.awt.*;
import java.applet.*;
public class Applet1 extends Applet {
void suspende3_Clicked(java.awt.event.ActionEvent event) {
pa3.suspende();
}
void resume3_Clicked(java.awt.event.ActionEvent event) {
pa3.resume();
}
void suspende2_Clicked(java.awt.event.ActionEvent event) {
pa2.suspende();
}
void resume2_Clicked(java.awt.event.ActionEvent event) {
pa2.resume();
}
void suspende1_Clicked(java.awt.event.ActionEvent event) {
pa1.suspende();
}
void resume1_Clicked(java.awt.event.ActionEvent event) {
pa1.resume();
}
void resetButton_Clicked(java.awt.event.ActionEvent event) {
suspendeButton_Clicked(null);
pa1.reset();
pa2.reset();
pa3.reset();
pa1.repaint();
pa2.repaint();
pa3.repaint();
}
void suspendeButton_Clicked(java.awt.event.ActionEvent event) {
pa1.suspende();
pa2.suspende();
pa3.suspende();
}
void resumeButton_Clicked(java.awt.event.ActionEvent event) {
pa1.resume();
pa2.resume();
pa3.resume();
}
public void init() {
super.init();
setLayout(new BorderLayout(0,0));
setSize(507,300);
mainButtonPanel = new java.awt.Panel();
mainButtonPanel.setLayout(new
FlowLayout(FlowLayout.CENTER,20,10));
mainButtonPanel.setBounds(0,257,507,43);
add("South", mainButtonPanel);
resumeButton = new java.awt.Button();
resumeButton.setLabel("Resume todos");
resumeButton.setBounds(155,10,55,23);
mainButtonPanel.add(resumeButton);
suspendeButton = new java.awt.Button();
suspendeButton.setLabel("Suspende Todos");
suspendeButton.setBounds(230,10,55,23);
mainButtonPanel.add(suspendeButton);
resetButton = new java.awt.Button();
resetButton.setLabel("Resseta");
resetButton.setBounds(305,10,47,23);
mainButtonPanel.add(resetButton);
animationArea = new java.awt.Panel();
animationArea.setLayout(new GridLayout(1,3,0,0));
animationArea.setBounds(0,0,507,257);
add("Center", animationArea);
aPanel1 = new java.awt.Panel();
aPanel1.setLayout(new BorderLayout(0,0));
aPanel1.setBounds(0,0,507,257);
aPanel1.setBackground(new Color(16711680));
animationArea.add(aPanel1);
ap1 = new java.awt.Panel();
ap1.setLayout(new FlowLayout(FlowLayout.CENTER,5,25));
ap1.setBounds(0,0,169,224);
aPanel1.add("Center", ap1);
subP1 = new java.awt.Panel();
subP1.setLayout(new FlowLayout(FlowLayout.CENTER,5,5));
subP1.setBounds(0,224,169,33);
aPanel1.add("South", subP1);
resume1 = new java.awt.Button();
resume1.setLabel("Resume");
resume1.setBounds(43,5,39,23);
subP1.add(resume1);
suspende1 = new java.awt.Button();
suspende1.setLabel("Suspende");
suspende1.setBounds(87,5,39,23);
subP1.add(suspende1);
aPanel2 = new java.awt.Panel();
aPanel2.setLayout(new BorderLayout(0,0));
aPanel2.setBounds(169,0,169,257);
animationArea.add(aPanel2);
ap2 = new java.awt.Panel();
ap2.setLayout(new FlowLayout(FlowLayout.CENTER,5,25));
ap2.setBounds(0,0,169,224);
aPanel2.add("Center", ap2);
subP2 = new java.awt.Panel();
subP2.setLayout(new FlowLayout(FlowLayout.CENTER,5,5));
subP2.setBounds(0,224,169,33);
aPanel2.add("South", subP2);
resume2 = new java.awt.Button();
resume2.setLabel("Resume");
resume2.setBounds(43,5,39,23);
subP2.add(resume2);
suspende2 = new java.awt.Button();
suspende2.setLabel("Suspende");
suspende2.setBounds(87,5,39,23);
subP2.add(suspende2);
aPanel3 = new java.awt.Panel();
aPanel3.setLayout(new BorderLayout(0,0));
aPanel3.setBounds(338,0,169,257);
aPanel3.setBackground(new Color(255));
animationArea.add(aPanel3);
ap3 = new java.awt.Panel();
ap3.setLayout(new FlowLayout(FlowLayout.CENTER,5,25));
ap3.setBounds(0,0,169,224);
aPanel3.add("Center", ap3);
subP3 = new java.awt.Panel();
subP3.setLayout(new FlowLayout(FlowLayout.CENTER,5,5));
subP3.setBounds(0,224,169,10);
aPanel3.add("South", subP3);
resume3 = new java.awt.Button();
resume3.setLabel("Resume");
resume3.setBounds(43,5,39,23);
subP3.add(resume3);
suspende3 = new java.awt.Button();
suspende3.setLabel("Suspende");
suspende3.setBounds(87,5,39,23);
subP3.add(suspende3);
ap1.add(pa1); // adição da Thread pa1
ap2.add(pa2); // adição da Thread pa2
ap3.add(pa3); // adição da Thread pa3
Acoes lAcoes = new Acoes();
resumeButton.addActionListener(lAcoes);
suspendeButton.addActionListener(lAcoes);
resetButton.addActionListener(lAcoes);
resume1.addActionListener(lAcoes);
suspende1.addActionListener(lAcoes);
resume2.addActionListener(lAcoes);
suspende2.addActionListener(lAcoes);
resume3.addActionListener(lAcoes);
suspende3.addActionListener(lAcoes);
}
java.awt.Panel mainButtonPanel;
java.awt.Button resumeButton;
java.awt.Button suspendeButton;
java.awt.Button resetButton;
java.awt.Panel animationArea;
java.awt.Panel aPanel1;
java.awt.Panel ap1;
java.awt.Panel subP1;
java.awt.Button resume1;
java.awt.Button suspende1;
java.awt.Panel aPanel2;
java.awt.Panel ap2;
java.awt.Panel subP2;
java.awt.Button resume2;
java.awt.Button suspende2;
java.awt.Panel aPanel3;
java.awt.Panel ap3;
java.awt.Panel subP3;
java.awt.Button resume3;
java.awt.Button suspende3;
relogio pa1 = new relogio(100); // criação da Thread pa1
relogio pa2 = new relogio(120); // criação da Thread pa2
relogio pa3 = new relogio(150); // criação da Thread pa3
class Acoes implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent event)
{
Object object = event.getSource();
if (object == resumeButton)
resumeButton_Clicked(event);
else if (object == suspendeButton)
suspendeButton_Clicked(event);
else if (object == resetButton)
resetButton_Clicked(event);
else if (object == resume1)
resume1_Clicked(event);
else if (object == suspende1)
suspende1_Clicked(event);
else if (object == resume2)
resume2_Clicked(event);
else if (object == suspende2)
suspende2_Clicked(event);
else if (object == resume3)
resume3_Clicked(event);
else if (object == suspende3)
suspende3_Clicked(event);
}
} // fim da classe Ações
} // fim da classe Applet1
Threads - Prioridades

Prioridades de
Linha
Quando uma linha de
prioridade baixa está
sendo executa e uma
linha de prioridade
mais alta torna-se
ativa, ou sai de uma
espera de E/S, ela é
executada
imediatamente.
class Clicador
implements Runnable {
int clique = 0;
private Thread t;
private boolean rodando = true;
public Clicador (int p) {
t = new Thread(this);
t.setPriority(p);
}
public void run( ) {
while (rodando) {
clique++;
}
}
public void stop( ) {
rodando = false;
}
public void start( ) {
t.start( );
}
}
Threads - Prioridades
class PriAltaBaixa {
public static void main (String args[ ]) {
Thread.currentThread( ).setPriority(Thread.MAX_PRIORITY);
Clicador alta = new Clicador(
Thread.NORM_PRIORITY + 2);
Clicador baixa = new Clicador(
Thread.NORM_PRIORITY - 2);
baixa.start( );
alta.start( );
try {
 O resultado da execução
Thread.sleep(10000); }
 deste programa é:
catch (Exception e) { };
 c:\> java PriAltaBaixa
baixa.stop( );
5785717 vs. 465881948
alta.stop( );
System.out.println(baixa.clique +
" vs." + alta.clique);
}
}
Bloqueio Mútuo
class A {
synchronized void foo(B b) {
class B {
String name =
synchronized void bar(A a) {
Thread.currentThread().getName();
String name =
System.out.println(name + "
Thread.currentThread().getName();
entrou em A.foo");
System.out.println(name + "
try { Thread.sleep(1000);} catch
entrou em B.bar");
(Exception e){ };
try { Thread.sleep(1000); } catch
System.out.println(name +
(Exception e) { };
" tentando chamarB.last()");
System.out.println(name +
b.last();
"tentando chamarA.last()");
}
a.last();
synchronized void last() {
}
System.out.println(" dentro de
synchronized void last() {
A.last");
System.out.println(" dentro de
}
B.last");
}
}
}
Bloqueio Mútuo (continuação)
class Deadlock implements Runnable {
A a = new A( );
B b = new B( );
Deadlock() {
Thread.currentThread( ).setName("MainThread");
new Thread(this).start( );
a.foo(b);
//consegue bloqueio a nesta linha.
System.out.println("de novo na linha principal");
}
public void run( ) {
Thread.currentThread( ).setName("RacingThread");
b.bar(a);
//consegue bloqueio em b em outra linha.
System.out.println("de novo em outra linha");
}
public static void main(String args[ ]) {
new Deadlock( );
}
} // fim da classe Deadlock
Bloqueio Mútuo (continuação)
O resultado deste programa é:
MainThread entrou em A.foo
RacingThread entrou em B.bar
MainThread tentando chamar B.last( )
RacingThread tentando chamar A.last( )
Java em Rede
Sockets e Threads
import java.io.*;
import java.net.*;
public class Envia extends Thread {
ObjectOutputStream os;
Socket s;
public Envia() {
super();
try {//s=new Socket(InetAddress.getLocalHost());
// s = new Socket("200.18.99.130",12345);
s = new Socket(“localhost",12345);
os = new
ObjectOutputStream(s.getOutputStream());
} catch(Exception e) {}
}
public static void main(String args[]) {
(new Envia()).start();
}
public void run( ) {
while (true) {
try { os.writeObject(new
Dados(1,"Testando dados"));
os.flush();
} catch (Exception e) {}
}
} }
import java.net.*;
import java.io.*;
public class trata extends Thread {
ObjectInputStream is;
Socket s;
public trata (Socket s) {
this.s = s;
try {
is = new ObjectInputStream(s.getInputStream());
} catch (Exception e)
{}
}
public void run( ) {
while (true) {
try {
Dados d = (Dados) is.readObject();
System.out.println(d.i);
System.out.println(d.a);
(new Thread(d)).start();
}catch(Exception e) {}
}
}
}
import java.io.*;
import java.net.*;
public class Recebe extends Thread {
ServerSocket s;
public Recebe() {
super();
try {
s = new ServerSocket(12345);
}catch(Exception e) {}
}
public static void main(String args[]) {
(new Recebe()).start();
}
public void run( ) {
try {
(new trata(s.accept())).start();
}catch(Exception e) {}
}
}
public class Dados extends Object
implements java.io.Serializable, Runnable {
public int i;
public String a;
public Dados (int i, String a) {
this.i = i;
this.a = a;
}
public void run () {
System.out.println(“Funcionou !!!!!!");
}
}
}
Para executar:
> Java Recebe
Em outra janela DOS:
> Java Envia
Explorando o java
java.util.concurrent
Operações Atômicas
Tipos: Integer, Long, Boolean, IntegerArray, e LongArray.
Acesso sincronizado pelas threads, através de operações
atômicas.
Por exemplo:
private AtomicLong val1
val1.incrementAndGet()
val1.get()
Pacote:
import java.util.concurrent.atomic.*;
Pacote java.util.concurrent.atomic.AtomicReference;
public class AtomicReference<V>
Serializable
implements
public AtomicReference()
public AtomicReference(V initialValue)
public final V get()
public final void set(V newValue)
public final boolean compareAndSet(V
expect, V update)
public final V getAndSet(V newValue)
package atomico;
import java.util.concurrent.atomic.AtomicReference;
public class Atomica extends AtomicReference<Integer> {
public Atomica() { }
public static void main(String args[]) {
Atomica a = new Atomica();
a.set(Integer.MIN_VALUE);
System.out.println("Teste1: " + a.get());
System.out.println("Teste2: " + a.getAndSet(22));
System.out.println("Teste1: " + a.get());
}
}
Saída:
Teste1: -2147483648
Teste2: -2147483648
Teste1: 22
Argumentos variáveis
menorNumero(1, 3, 2, 7);
menorNumero(3, 6, 1, 8, 3, 9, 0);
public static Integer menorNumero
(Integer a, Integer b)
public static Integer menorNumero
(Integer... numeros)
Tipos Genéricos
Usa padrão formatado de uma categoria sintática em Tempo de
Compilação;
Observações:
List<String> NÃO é Subtipo de List<Object>
List<?> NÃO é o Mesmo que List<Object>
List<String> É Subtipo de List<? extends Object>
List<Integer> É Subtipo de List<? extends Number>
List<?>
Lista de Qualquer Coisa
extends (Leia, Que Seja Subtipo)
List<? extends Number>
Lista de Qualquer Coisa que Seja Subtipo de Number
super (Leia, Que Seja Supertipo)
List<? super ArrayList>
Lista de Qualquer Coisa que Seja Supertipo de ArrayList
public interface Callable<V>
A task that returns a result and may throw an exception.
Implementors define a single method with no arguments called call.
The Callable interface is similar to Runnable, in that both are designed
for classes whose instances are potentially executed by another
thread.
A Runnable, however, does not return a result and cannot throw a
checked exception.
public interface Executor
An object that executes submitted Runnable tasks. This interface
provides a way of decoupling task submission from the mechanics of
how each task will be run, including details of thread use, scheduling,
etc.
An Executor is normally used instead of explicitly creating threads.
For example, rather than invoking
new Thread(new(RunnableTask())).start() ;
for each of a set of tasks, you might use:
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
...
public interface ExecutorService extends Executor
An Executor that provides methods to manage termination and
methods that can produce a Future for tracking progress of one or
more asynchronous tasks.
An ExecutorService can be shut down, which will cause it to reject new
tasks. Two different methods are provided for shutting down an
ExecutorService. The ExecutorService.shutdown method will allow
previously submitted tasks to execute before terminating, while the
ExecutorService.shutdownNow method prevents waiting tasks from
starting and attempts to stop currently executing tasks. Upon
termination, an executor has no tasks actively executing, no tasks
awaiting execution, and no new tasks can be submitted. An unused
ExecutorService should be shut down to allow reclamation of its
resources.
public interface ExecutorService extends Executor
Method submit extends base method Executor.execute by creating
and returning a Future that can be used to cancel execution and/or
wait for completion. Methods invokeAny and invokeAll perform the
most commonly useful forms of bulk execution, executing a collection
of tasks and then waiting for at least one, or all, to complete. (Class
ExecutorCompletionService can be used to write customized variants
of these methods.)
The Executors class provides factory methods for the executor
services provided in this package.
Here is a sketch of a network service in which threads in a thread
pool service incoming requests. It uses the preconfigured
Executors.newFixedThreadPool factory method
class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port, int poolSize)
throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
}
public void run() { // run the service
try {
for (;;) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
pool.shutdown();
} }}
class Handler implements Runnable {
private final Socket socket;
Handler(Socket socket) { this.socket = socket; }
public void run() {
// read and service request on socket
}
}
The following method shuts down an ExecutorService in two phases,
first by calling shutdown to reject incoming tasks, and then calling
shutdownNow, if necessary, to cancel any lingering tasks.
void shutdownAndAwaitTermination(ExecutorService pool)
{
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}}
public interface Future<V>
Future represents the result of an asynchronous computation.
Methods are provided to check if the computation is complete, to wait
for its completion, and to retrieve the result of the computation. The
result can only be retrieved using method get when the computation
has completed, blocking if necessary until it is ready. Cancellation is
performed by the cancel method. Additional methods are provided to
determine if the task completed normally or was cancelled. Once a
computation has completed, the computation cannot be cancelled. If
you would like to use a Future for the sake of cancellability but not
provide a usable result, you can declare types of the form Future<?>
and return null as a result of the underlying task.
Parâmetros:
V - The result type returned by this Future's get method
<T> Future<T> submit(Callable<T> task)
void shutdown()
List<Runnable> shutdownNow()
boolean awaitTermination
(long timeout, TimeUnit unit)
throws InterruptedException
interface ArchiveSearcher { String search(String target); }
class App {
ExecutorService executor = ...
ArchiveSearcher searcher = ...
void showSearch(final String target) throws InterruptedException {
Future<String> future = executor.submit (new Callable<String>() {
public String call() { return searcher.search( target); }});
displayOtherThings();
// do other things while searching
try { displayText(future.get());
// use future
} catch (ExecutionException ex) { cleanup(); return; } } }
The FutureTask class is an implementation of Future that implements Runnable, and
so may be executed by an Executor.
For example, the above construction with submit could be replaced by:
FutureTask<String> future = new FutureTask<String>(new Callable<String>() {
public String call() { return searcher.search(target); }} );
executor.execute(future);
Tarefas Agendadas
public <V> ScheduledFuture<V>
schedule(Callable<V> callable,
long delay, TimeUnit unit)
public ScheduledFuture<?>
scheduleAtFixedRate(Runnable
command,
long initialDelay, long period, TimeUnit unit)
public ScheduledFuture<?> scheduleWithFixedDelay
(Runnable command,
long initialDelay, long delay, TimeUnit unit)
public interface BlockingQueue<E>
extends Queue<E>
A Queue that additionally supports operations that wait
for the queue to become non-empty when retrieving
an element, and wait for space to become available
in the queue when storing an element.
A BlockingQueue does not accept null elements.
Exemplo Produtor e Consumidor
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try { while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
public class ArrayBlockingQueue<E>
extends AbstractQueue<E>
implements BlockingQueue<E>, Serializable
A bounded blocking queue backed by an array.
This queue orders elements FIFO (first-in-first-out).
The head of the queue is that element that has been on
the queue the longest time. The tail of the queue is
that element that has been on the queue the shortest time.
New elements are inserted at the tail of the queue, and the
queue retrieval operations obtain elements at the head of
the queue.
public class CountDownLatch extends Object
A synchronization aid that allows one or
more threads to wait until a set of operations
being performed in other threads completes.
A CountDownLatch is initialized with a given count.
The await methods block until the current count
reaches zero due to invocations of the
CountDownLatch.countDown method, after
which all waiting threads are released and
any subsequent invocations of await return immediately.
Meta Classes
package geral.reflex;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class TesteReflection {
...
public static void main(String[] args) {
Field[] campos = TesteReflection.class.getDeclaredFields();
for (Field campoAtual : campos) {
System.out.println(campoAtual.getName() + ": " +
campoAtual.getType().getName());
}
}
Constructor<TesteReflection>[] constr = (Constructor<TesteReflection>[])
TesteReflection.class.getDeclaredConstructors();
System.out.println("Construtores de TesteReflection:");
for (Constructor<TesteReflection> constrAtual : constr) {
try {
Class<?>[] params = constrAtual.getParameterTypes();
System.out.print("\t");
System.out.print(Modifier.toString(constrAtual.getModifiers()));
System.out.print(" TesteReflection(");
if (params.length > 0) {
System.out.print(params[0].getName());
for (int i = 1; i < params.length; i++) {
System.out.print(", ");
System.out.print(params[i].getName());
}
}
System.out.println(")");
} catch (Exception e) {
e.printStackTrace();
}
}
TesteReflection var =
new TesteReflection("Primeiro Teste");
try {
Field campo =
TesteReflection.class.getDeclaredField("algo");
System.out.println("\nCampo: " + campo +
" contendo: " + campo.get(var));
Method metodo =
TesteReflection.class.getDeclaredMethod("getAlgo");
if (metodo != null) {
System.out.println(metodo.getName()+ " retorna: "+
metodo.invoke(var));
}
} catch (Exception e) {
e.printStackTrace();
}
}
Outras Linguagens
Concorrentes:
Ada
Modula
Ada – Introdução
Ada é uma linguagem de programação de alto nível e
imperativa baseada em Pascal e criada através de um
concurso realizado pelo Depto. de Defesa dos EUA. O
nome Ada é uma homenagem a condessa de Lovelace,
Augusta Ada Byron, filha de Lord Byron que trabalhou
com Charles Babbage e é considerada como a primeira
programadora de computadores da História.
Ada – Características
•Grande capacidade numérica tornando-a útil para
uso acadêmico;
•Foi projetada para detectar erros não apenas durante
a compilação mas também em tempo de execução;
•Foi feita para implementar programas rápidos e para
ser usada em máquinas que usam computadores para
fins militares;
•É uma linguagem estruturada, imperativa e
fortemente tipada;
•Ada 95 suporta programação orientada ao objeto e
permite interfaces com C/C++, FORTRAN e também
com Java;
Ada – Estruturas básicas
Declarações de eventuais bibliotecas
Procedure nome_do_programa is
Declarações de possíveis variáveis
Begin
Corpo do programa
End nome_do_programa;
Exemplo:
with Text_IO; use Text_IO;
procedure alomundo is
begin
Put_Line("Alo Mundo!!!");
end alomundo;
Ada – Estruturas básicas
Declaração de bibliotecas
With Ada.Text_IO;
Declaração de Variáveis.
Nome_variável : tipo_variável [:= valor];
Comentário
Tudo o que estiver a direita de "--" é comentário no
programa.
Ada – Comandos
IF
if condição then
seqüência de comandos
elsif condicao2 then
seqüência de comandos2
else
outra seqüência de comandos
end if;
FOR
for a in 1..10 loop
sequencia de comandos
end loop;
Ada – Comandos
While
while a /=3 and b <=15 and c=3.0 loop
seqüência de comandos
end loop;
Loop-laço
loop
seqüência de comandos
end loop;
Case
case x is
when 1 => executa alguma coisa
when others => Put_Line("Oi");
end case;
Ada – Concorrência
A concorrência em Ada pode ser expressada através de
tarefas (tasks). São entidades passivas que fornecem
serviços de gerenciamento para dados compartilhados
armazenados neles. Eles fornecem seus serviços, mas
somente quando eles são solicitados. As tarefas Ada
possuem diversos mecanismos que permitem a escolha
entre solicitações concorrentes para acesso a seus
recursos. As tarefas são declaradas em duas partes,
uma de especificação e uma de corpo através das
clausula entry e accept .
Ada – Concorrência
•As tarefas comunicam-se usando mecanismo de
passagem de mensagem (rendezvous);
•Quando um accept recebe uma mensagem que não
está preparado para aceitar, a tarefa emissora deve ser
suspensa até que a tarefa receptora esteja preparada
para receber a mensagem
•Accept trabalha com uma fila associada;
Task body Tarefa is
begin
loop
Accept entrada(parametros) do
..................
end entrada;
end loop;
end tarefa;
Ada – Concorrência
Um outro exemplo mostra como mais de uma tarefa são
tratadas:
Task body tarefa is
loop
Fila
select
Seção crítica
accept entrada_1 (parâmetros) do
controlada
.....
pelos comandos
end entrada_1;
Fila
Accept e
or
select
accept entrada_2 (parâmetros) do
.....
end entrada_2;
end select;
O select examina as filas
end loop;
selecionando qual accept
end tarefa;
será executado primeiro
Ada – Concorrência
Pode ser feita também a sincronização de competição,
onde a clausula accept pode ter uma proteção(guarda)
anexada, na forma do comando when podendo retardar
o mecanismo.
when not cheio(buffer) =>
accept deposita(novo) do
Um accept com um when pode ser aberto ou fechado.
Se a expressão boolena da when for verdadeira, accept
será aberto e estará sempre disponível para rendezvous,
caso contrário será fechado e não poderá ter
rendezvous.
Ada – Concorrência
Produtor/consumidor
with Ada.Integer_text_IO,Ada.Text_IO;
use Ada.Integer_Text_IO,Ada.Text_IO;
-- Bibliotecas usadas -procedure Prod_Cons is -- Procedimento principal ---Declaração da tarefa buffer e seus métodos-Define o nome do
task buffer is
entry deposita(ITEM : in INTEGER);
método que será
entry busca(ITEM : out INTEGER);
usado na
end buffer;
concorrência
--Estrutura corpo do buffer-task body buffer is
tambuffer:constant INTEGER :=100;
buf : array(1..tambuffer) of INTEGER;
preenchido : INTEGER range 0..tambuffer := 0;
prox_in,prox_out : INTEGER range 0..tambuffer := 1;
ITEM : INTEGER;
Ada – Concorrência
begin
loop
select
when preenchido < tambuffer =>
accept deposita(ITEM :in INTEGER) do o accept determina
buf(prox_in) := ITEM;
quem vai entrar para
end deposita;
prox_in := (prox_in mod tambuffer) + 1; acessar o recurso
preenchido := preenchido + 1;
seleciona qual
or
when preenchido > 0 =>
método será usado
accept busca(ITEM : out INTEGER) do
ITEM := buf(prox_out);
end busca;
prox_out := (prox_out mod tambuffer) + 1;
preenchido := preenchido - 1;
end select;
end loop;
end buffer;
Ada – Concorrência
task produtor;
Declarações das tarefas que
task consumidor;
task body produtor is
vão acessar os métodos do buffer
novo_valor : INTEGER;
begin
loop
buffer.deposita(novo_valor);
put_line("Produzindo...");
Os métodos estão
end loop;
end produtor;
sendo chamados
task body consumidor is
da task buffer,
valor_armazenado : INTEGER;
que é comum as
begin
loop
outras tarefas
buffer.busca(valor_armazenado);
put_line("Consumindo...");
-- consome valor_armazenado -end loop;
end consumidor;
end Prod_Cons;
Ada – Concorrência
Objetos Protegidos
•Oferece sincronização por competição que não envolve
o mecanismo de rendezvous.
•Podem ser acessados ou por sub-programas
protegidos ou por entradas similares existentes em
tarefa.
•Esses objetos oferecem acesso mutuamente exclusivo
de leitura e escrita aos dados e funções do objeto, que
oferecem acesso concorrente.
•As chamadas de entrada a um objeto protegido
proporcionam comunicação síncrona com uma ou mais
tarefas usando o mesmo objeto protegido
Ada – Concorrência
protected body buffer is
accept deposita(ITEM :in INTEGER) do
when preenchido < tambuffer is
begin
buf(prox_in):= ITEM;
prox_in := (prox_in mod tambuffer) + 1;
preenchido := preenchido + 1;
end deposita;
accept busca(ITEM : out INTEGER) when preenchido > 0 is
begin
ITEM := buf(prox_out);
prox_out := (prox_out mod tambuffer) + 1;
preenchido := preenchido - 1;
end busca;
end loop;
end buffer;
Ada – Concorrência
Semáforos
Nesse exemplo estão implementadas duas tarefas, que
são controladas pelo semáforo
with TEXT_IO, SEMAPHORES;
use TEXT_IO, SEMAPHORES;
procedure EXAMPLE is
SCREEN : SEMAPHORE;
task ONE;
task body ONE is
begin
loop
WAIT (SCREEN);
PUT_LINE (“Tarefa 1");
SIGNAL (SCREEN);
end loop;
end ONE;
task TWO;
task body TWO is
begin
loop
WAIT (SCREEN);
PUT_LINE (“Tarefa 2");
SIGNAL (SCREEN);
end loop;
end TWO;
begin
INITIAL (SCREEN, 1);
end EXAMPLE;
Ada – Concorrência
Tela do programa Ada+SQL
Modula – Introdução
•Criada em 1975 pelo professor Niklaus Wirth, criador da
linguagem Pascal
•linguagem segura, confiável e com muito mais recursos
que o Pascal;
Apresenta as seguintes características:
Modula – Características
•Linguagem fortemente tipada, com grande variedade de
tipos e estruturas de controle;
•Faz menos uso de blocos (begin...end), otimizando
estruturas de controle como if e for;
• Eliminou o label e goto;
•Capacidade de criar programas utilizando multiprocessamento através de co-rotinas;
•Case sensitive
Modula
Estruturas Básicas
MODULE Nome_Programa;
Declaração de bibliotecas;
Declaração de variáveis;
Begin
Corpo do programa;
End Nome_programa.
Exemplo:
MODULE Exemplo;
FROM InOut IMPORT WriteString, WriteInt, WriteLn;
VAR digito: INTEGER;
BEGIN
WriteString(“âlo mundo”);
END Exemplo.
(* Fim do Programa*)
Modula
Estruturas Básicas
Declaração de bibliotecas
FROM IO IMPORT WriteString ,WriteCard ,Writeln;
Declaração de variáveis
VAR Nome_variável : Tipo_da_variável;
Comentário
Tudo que estiver entre ( *....*) é comentário do
programa.
Modula – Comandos
IF
Exemplo:
IF maior > menor THEN
Verdade := maior
ELSE
HALT;
END;
Case
CASE variável
OF
constante 1: comando 1;
constante 2: comando 2;
constante n: comando n;
END;
Modula – Comandos
While
WHILE condição DO
comandos;
END;
Repeat
REPEAT
comandos;
UNTIL condição;
Loop
LOOP
Seqüência de Estruturas
END
Modula – Comandos
For
soma :=0;
FOR i :=1 TO n BY 2 DO
soma := soma + i * i
END;
With
WITH designador DO
SeqComandos
END;
Modula – Declarações
Uma declaração de procedure deve ter:
o nome da procedure;
 informação sobre os parâmetros da procedure(se
existirem);
 o tipo de valor que a procedure retorna (se é uma
função);
 declaração das entidades que pertencem à procedure;
uma seqüência de estruturas para serem executadas
quando a procedure é chamada.
Sintaxe:
procedure <identificador>;
OU
procedure <identificador> ( parâmetros );
Modula – Declarações
Função
São métodos que realizam cálculos e retornam um valor.
Exemplo:
PROCEDURE potencia (x:REAL; i:INTEGER):REAL;
VAR z:REAL;
BEGIN z:=1.0;
WHILE i>0 DO
IF ODD(i) THEN z:=z*x END;
x:= x*x; i:=i DIV 2;
END;
RETURN z;
END potencia;
Modula – Módulos
•Os módulos são características que distinguem o
Modula do seu ancestral, o Pascal;
• Todo programa em Modula é um módulo, ou, na
maioria das vezes, é formados por um programa módulo
(programa principal), e por um número qualquer de
módulos de biblioteca;
•Módulos locais, declarados dentro de outros módulos
ou procedures;
•Nem todas as entidades pertencem a um módulo assim
como nem todas entidades declaradas em outros
módulos estão disponíveis para este módulo;
Modula – Concorrência
•Pode-se definir um processo como sendo um
programa em execução;
•Definimos concorrência quando dois ou mais
processos são executados simultaneamente sem que
nenhum destes seja prejudicado ;
•Em Modula implementa-se "concorrência" através das
Co-rotinas.
Modula – Concorrência
Definição de um Módulo Processes:
DEFINITION MODULE Processes;
TYPE SIGNAL;
PROCEDURE StartProcess(P:PROC; n:INTIGER);
(*inicia um processo concorrente*)
PROCEDURE SEND(VAR s:SIGNAL);
(*um processo esperando por um s é continuado*)
PROCEDURE WAIT(VAR s:SIGNAL);
(*espera algum processo enviar s*)
PROCEDURE Awaited(s:SIGNAL):BOOLEAN;
(*Acordado(s)=“pelo menos um processo espera por s”*)
PROCEDURE Init(VAR s:SIGNAL);
(*inicialização compulsória*)
END Processes.
Modula – Concorrência
•As Co-rotinas são implementadas a partir da procedure
NewProcess;
•Co-rotinas necessitam de programas ou procedures que
manipulem valores de endereços de memória, pois elas
agem diretamente no hardware do computador;
•Na chamada da procedure NewProcess deve ser
especificada em qual será criada a Co- rotina, o
Workspace que é o bloco de memória onde será
armazenado o estado da Co-rotina, o endereço de
memória do Workspace,o tamanho do Workspace e a
referência para a nova Co-rotina;
Modula – Concorrência
Sintaxe de NewProcess:
Procedure NewProcess ( P : Procedure; A :
Address "endereço do Workspace"; S : Cardinal
"tamanho do Workspace"; Var E : Address
"referência para nova Co-rotina");
Antes de chamarmos a procedure NewProcess
devemos alocar memória para a Workspace, pois é
nela que ficam as variáveis locais, a Co-rotina e a
pilha de Co-rotinas e outras informações. Para
criarmos a Workspace devemos declarar um array de
Bytes ou Words. Também devemos criar uma variável
do tipo Address, que retornará o endereço e o
tamanho do Workspace(ADR e SIZE).
Modula – Concorrência
A procedure Transfer tem a função de transferir o
controle de execução de uma Co-rotina para outra
caracterizando a concorrência, ela também é
fundamental para executar as Co-rotinas, pois
NewProcess apenas prepara a Co-rotina para a
execução. Esta é a sintaxe da procedure Transfer:
Procedure Transfer ( A, B : Address);
Quando a procedure Transfer é chamada, ela
interrompe a Co-rotina que está sendo executada no
momento, que é referenciada por A, e inicia a outra
que é referenciada por B. A procedure Transfer deve
ser importada de System.
Modula – Concorrência
MODULE Aplic;
FROM Nucleo IMPORT CriarProcesso, DestruirProcesso, Boot,
EnviarMsg, ReceberMsg, TipoNome, TipoMsg,
TamNome, TamMsg, Sempre, NemSempre,EscreveFrase,
EscreveInt,Incrementa,MaiorIgual,Atribui;
FROM InOut IMPORT WriteCard, WriteLn, WriteString, WriteInt;
CONST TamBuffer = 10;
TYPE TipoBuffer = ARRAY[0..TamBuffer-1] OF TipoMsg;
VAR
BufferIn,BufferOut : TipoBuffer;
In,Out
: INTEGER;
Flag
: BOOLEAN;
Modula – Concorrência
PROCEDURE InicializaBuffer;
VAR I : CARDINAL;
BEGIN
BufferIn[0] := 'MENSAGEM BUFFERIZADA NUMERO 1';
BufferIn[1] := 'MENSAGEM BUFFERIZADA NUMERO 2';
....
BufferIn[10] := 'MENSAGEM BUFFERIZADA NUMERO 11';
FOR I := 0 TO (TamBuffer - 1) DO
BufferOut[I] := '
';
END; (* FOR *)
In := 0;
Out := 0;
END InicializaBuffer;
Modula – Concorrência
PROCEDURE PoeNoBuffer(Msg : TipoMsg);
BEGIN
EscreveFrase('VAI POR NO BUFFER');
EscreveFrase(Msg);
EscreveInt(Out);
Atribui(BufferOut[Out],Msg);
Incrementa(Out);
END PoeNoBuffer;
O produtor e o
Consumidor acessam
Esses métodos
de modo
concorrente
PROCEDURE TiraDoBuffer(VAR Msg : TipoMsg);
BEGIN
EscreveFrase('VAI TIRAR DO BUFFER');
EscreveInt(In);
Atribui(Msg,BufferIn[In]);
Incrementa(In);
EscreveFrase(Msg);
END TiraDoBuffer;
Modula – Concorrência
PROCEDURE Produtor;
VAR Msg : TipoMsg;
Flag : BOOLEAN;
BEGIN
EscreveFrase('ENTROU NO PRODUTOR');
LOOP
TiraDoBuffer(Msg);
EnviarMsg(Msg,'C1',Flag);
IF MaiorIgual(In,TamBuffer)
THEN DestruirProcesso(NemSempre,Flag);
END; (* IF *)
END; (* LOOP *);
EscreveFrase('SAIU DO PRODUTOR');
END Produtor;
O produtor é
criado no inicio
do programa se
o buffer estiver
cheio, ele é
destruído
Modula – Concorrência
PROCEDURE Consumidor;
VAR Msg : TipoMsg;
Flag : BOOLEAN;
BEGIN
EscreveFrase('ENTROU NO CONSUMIDOR');
LOOP
ReceberMsg(Msg,Flag);
IF Flag
THEN
PoeNoBuffer(Msg);
END;
IF MaiorIgual(Out,TamBuffer)
THEN DestruirProcesso(NemSempre,Flag);
END; (* IF *)
END; (* LOOP *)
EscreveFrase('SAIU DO CONSUMIDOR');
END Consumidor;
Download