在两个线程和主程序之间共享一个对象

11

我刚学Java,正在上并发编程课程。我急需一个最小的工作示例,可以帮助演示我所学的概念,例如使用“synchronized”关键字和在线程之间共享对象。我一直在搜索,但找不到基本框架。Java程序员,请帮忙。

2个回答

8
一个简单的例子。希望你喜欢足球(或者叫做足球)。 :)
public class Game {

 public static void main(String[] args) {
  Ball gameBall = new Ball();
  Runnable playerOne = new Player("Pasha", gameBall);
  Runnable playerTwo = new Player("Maxi", gameBall);

  new Thread(playerOne).start();
  new Thread(playerTwo).start();
 }

}

public class Player implements Runnable {

 private final String name;
 private final Ball ball;

 public Player(String aName, Ball aBall) {
  name = aName;
  ball = aBall;
 }

 @Override
 public void run() {
  while(true) {
   ball.kick(name);
  }
 }

}

public class Ball {

private String log;

 public Ball() {
  log = "";
 }

 //Removing the synchronized keyword will cause a race condition.
 public synchronized void kick(String aPlayerName) {
  log += aPlayerName + " ";
 }

 public String getLog() {
  return log;
 }

}

实例化几个更多的Player对象,以使其更加明显。 - Mike
就我所看到的,它将在玩家名称之间交替。但是,并不一定每隔一个交替,因为这就是上下文切换的工作原理。 - jjnguy
实例化几个,删除同步关键字。ThreadA进入调用System.out.println()。ThreadB不久之后也这样做。嘭。 - Mike
没问题,请再检查一遍。 :) - Mike
@Mike:你可以将字符串附加到 ArrayList<String> 中。这是我最初考虑的一个很好的例子(即两个线程在没有适当同步的情况下调用同一对象上的线程不安全方法)。 - Daniel Trebbien
显示剩余7条评论

6
这是一个在两个线程之间共享数组的简短示例。通常情况下,您会看到全部为零,但有时会出现其他数字。
final int[] arr = new int[100];
Thread one = new Thread() {
    public void run() {
        // synchronized (arr) {
            for (int i = 0; i < arr.length * 100000; i++) {
                arr[i % arr.length]--;
            }
        // }
    }
};
Thread two = new Thread() {
    public void run() {
        // synchronized (arr) {
            for (int i = 0; i < arr.length * 100000; i++) {
                arr[i % arr.length]++;
            }
        //}
    }
};
one.start();
two.start();
one.join();
two.join();
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

但是,如果你在循环中同步arr,你将总是在打印输出中看到所有的0。如果你取消注释同步块,代码将可以正常运行。


2
您还可以通过在增量和减量行上同步arr来消除错误:http://pastebin.com/vN4E527P 这强调了唯一不安全的线程部分就是这两行。 - Daniel Trebbien
有时我会得到一串随机数字的字符串。我感到困惑。您能否请解释一下它的工作原理? - softwarematter
arr[i % arr.length]--和arr[i % arr.length]++不应该平衡执行相同次数吗?换句话说,结果难道不应该始终为零吗? - softwarematter
2
@n0vi 是的,这正是共享对象在多个线程中引起问题的绝佳例子。发生的情况是两个线程同时尝试增加和减少数组中的同一项,其中一个会覆盖另一个,因此您不会看到应该看到的所有 0 - jjnguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接