1

I am coding a program similar to producer-consumer in java (but with the consumer only portion, with no producer thread). It looks like the critical region is being executed at the same time by multiple threads despite the fact that I am calling the code of a synchronized method.

Here is the code:

Class Main.java:

package principal;

public class Main {

/**
 * @param args
 */
public static void main(String[] args) {
    final int tamanho_buffer=10;
    final int quantidade_threads=10;

    Pedido buffer[] = new Pedido[tamanho_buffer];
    Consumidor consumidor[] = new Consumidor[quantidade_threads];

    for (int i=0;i<tamanho_buffer;i++) {
        buffer[i]=new Pedido();
    }

    for (int i=0;i<quantidade_threads;i++) {
        consumidor[i]=new Consumidor();
    }

    for (int i=0;i<tamanho_buffer;i++) {
        int identificador[]=new int[Pedido.getTamanho_identificador()];
        identificador[0]=i;
        buffer[i].setIdentificador(identificador);
        buffer[i].setTexto("pacote de dados");
    }

    Consumidor.setBuffer(buffer);
    Consumidor.setTamanho_buffer(tamanho_buffer);

    for (int i=0;i<quantidade_threads;i++) {
        consumidor[i].start();
    }

    for (int i=0;i<quantidade_threads;i++) {
        try {
            consumidor[i].join();
        }catch(InterruptedException e ){
            System.out.println("InterruptedException lancada");
        }
    }

    System.out.println("Processamento encerrado.");

}

}

Class Pedido.java:

package principal;

    public class Pedido {
private int identificador[];
private String texto;
static int tamanho_identificador=10;
int ti=tamanho_identificador;

public Pedido() {
    this.identificador= new int[this.ti];
}

public static int getTamanho_identificador() {
    return tamanho_identificador;
}

public int[] getIdentificador() {
    return identificador;
}
public void setIdentificador(int[] identificador) {
    this.identificador = identificador;
}
public String getTexto() {
    return texto;
}
public void setTexto(String texto) {
    this.texto = texto;
}

}

Class Consumidor.java

package principal;

import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class Consumidor extends Thread {

private static Pedido buffer[];
private static int tamanho_buffer;
private static int posicao=0;

public static void setTamanho_buffer(int tamanhoBuffer) {
    tamanho_buffer = tamanhoBuffer;
}

public static void setBuffer(Pedido[] buffer) {
    Consumidor.buffer = buffer;
}

public void run() {
    DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    while (posicao < Consumidor.tamanho_buffer ) {
   //           int identificador;
   //           identificador=buffer[posicao].getIdentificador()[0];;

        Date datainicio = new Date();
        String inicio=dateFormat.format(datainicio);

        try {
            Consumidor.sleep(1000);
        } catch(InterruptedException e) {
            System.out.println("InterruptedException lancada");
        }

        Date datafim = new Date();
        String fim=dateFormat.format(datafim);

        consomebuffer(inicio,fim);

    }
}

synchronized void consomebuffer(String inicio, String fim) {
    if (posicao < Consumidor.tamanho_buffer ) {
        int identificador;
        identificador=buffer[posicao].getIdentificador()[0];
        System.out.println("Thread: "+Thread.currentThread()+" Pedido: "+identificador+" Inicio: "+inicio+" Fim: "+fim+" posicao "+posicao);
        posicao++;
    }
}
}

The method consomebuffer is synchronized but it looks like the variable posicao (portuguese name for position) is being accessed by the other threads at the same time, that should not happen, coz it is a synchronized method. The program output is something like this:

Thread: Thread[Thread-7,5,main] Pedido: 0 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 0

Thread: Thread[Thread-6,5,main] Pedido: 0 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 0

Thread: Thread[Thread-2,5,main] Pedido: 0 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 0

Thread: Thread[Thread-9,5,main] Pedido: 0 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 0

Thread: Thread[Thread-3,5,main] Pedido: 4 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 4

Thread: Thread[Thread-5,5,main] Pedido: 5 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 5

Thread: Thread[Thread-0,5,main] Pedido: 0 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 5

Thread: Thread[Thread-8,5,main] Pedido: 0 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 5

Thread: Thread[Thread-4,5,main] Pedido: 5 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 5

Thread: Thread[Thread-1,5,main] Pedido: 0 Inicio: 2011/09/24 21:14:18 Fim: 2011/09/24 21:14:19 posicao 0

Processamento encerrado.

Realize that the position value is appearing repeated between different threads. In the output posicao should have a different value in each thread that calls the synchronized method.

4

1 回答 1

2

每个 Thread 实例都在自己同步。为了使所有线程互斥,它们必须在一个公共对象上同步。

那是,

public synchronized method(int parameter)
{
    //do some stuff
}

是简写

public method(int parameter)
{
    synchronized (this)
    {
        //do some stuff
    }
}

如果你想让一堆线程相互同步,你需要为它们提供一个公共对象来同步。

例如,您可以添加 Consumidor.java 的构造函数

public Consumidator(Object monitor)
{
     myMonitor = monitor
}

然后在运行中有

void consomebuffer(String inicio, String fim) {
  synchronized (myMonitor)
  {
    if (posicao < Consumidor.tamanho_buffer ) {
        int identificador;
        identificador=buffer[posicao].getIdentificador()[0];
        System.out.println("Thread: "+Thread.currentThread()+" Pedido: "+identificador+" Inicio: "+inicio+" Fim: "+fim+" posicao "+posicao);
        posicao++;
    }
  }
}

然后,当您创建 Consumidadors 数组时,将共享对象传递给它们以进行同步。

于 2011-09-25T00:57:39.587 回答