什么时候线程共享对象? - Java

时间:2013-11-25 17:37:11

标签: java multithreading

嘿,我正在努力把线程作为一个概念。 我来画一个场景

class A {
    private int counter = 0;

    public void add() {
        counter++;
    }

    public int getCounter() {
        return counter;
    } 
}

class B implements Runnable {
    public void run() {
        A a = new A();
        a.add();
        a.add();
    }
}

class C implements Runnable {
    public void run() {
        A a = new A();
        System.out.println(a.getCounter());
    }
}

System.out.println运行时C给了我什么? 我猜它给了我0因为他们每个都创建了一个A的实例。

如果这是真的,你会如何在线程之间共享该对象?

2 个答案:

答案 0 :(得分:2)

您在System.out上看不到任何内容,因为您没有完整的程序。但是,假设你创建了两个线程,并用一个运行B,然后用另一个运行C,是的,0将被打印,因为正如你猜测的那样,每个线程使用一个单独的A实例。这很好,因为A没有'有任何内存障碍,可以让多个线程安全地访问它。

要共享数据,您需要将一个对象传递给两个线程。例如:

final class Test {

  public static void main(String[] argv) throws InterruptedException {
    AtomicInteger shared = new AtomicInteger();
    Thread a = new B(shared).start();
    a.join();
    Thread b = new C(shared).start();
    b.join();
  }

}

final class B extends Thread {

  private final AtomicInteger shared;

  B(AtomicInteger shared) { this.shared = shared; }

  @Override()
  public void run() {
    shared.getAndIncrement();
    shared.getAndIncrement();
  }

}

final class C extends Thread {

  private final AtomicInteger shared;

  C(AtomicInteger shared) { this.shared = shared; }

  @Override()
  public void run() {
    System.out.println(shared.get());
  }

}

这将打印2,因为主要方法是确保线程顺序运行。在更现实的方法中,线程将同时启动,并且将打印0,1或2,具体取决于相对时间。

答案 1 :(得分:1)

您在控制台中看到的内容(假设某些实例化C并将其传递给执行它的线程)将为0,因为没有其他内容正在写入该A实例.a是run方法的局部变量,没有否则可以看到它。

多线程访问是指对象在线程之间传递的时间。一个典型示例是队列,其中您有不同的线程写入数据结构,而其他线程从同一数据结构中删除对象。 写入队列(生产者)的每个线程都会创建对象并将它们放入队列中。相同的对象将由不同的线程(称为消费者)检索,这些线程专用于从队列中获取对象并使用它们执行某些操作。因此,生产者创建的对象将被放置在队列中并保持在那里直到消费者获取它为止。

这是一个简单的队列实现。它使用synchronized来锁定内部列表,以便一次只有一个线程可以访问队列。

public class MyQueue<T> {

    private List<T> list = new ArrayList<T>();

    public T take() throws InterruptedException  {
        synchronized(list) {
            while (list.size() == 0) {
                list.wait();
            }
            return list.remove(0);
        }
    }

    public void put(T object) {
        synchronized(list) {
            list.add(object);
            list.notifyAll();
        }
    }
}