【问题标题】:Sharing an object between two threads and main program在两个线程和主程序之间共享一个对象
【发布时间】:2011-04-06 01:12:15
【问题描述】:

我是 Java 新手,正在参加并发编程课程。我正在拼命地尝试获得一个最小的工作示例,它可以帮助演示我学到的概念,例如使用“同步”关键字和跨线程共享对象。 一直在寻找,但没有得到一个基本的框架。 Java 程序员,请帮忙。

【问题讨论】:

    标签: java concurrency synchronized


    【解决方案1】:

    一个简单的例子。希望你喜欢足球(或足球)。 :)

    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 对象以使其更明显。
    • 据我所知,它会在玩家姓名之间交替出现。但是,不一定是其他的,因为这正是上下文切换的工作原理。
    • 再实例化几个,去掉 synchronized 关键字。 ThreadA 移入调用 System.out.println()。 ThreadB 不久之后就这样做了。布拉莫。
    • @Mike,好吧,我会在批评之前自己尝试一下。
    • 没关系。仔细检查我。 :)
    【解决方案2】:

    这是一个在两个线程之间共享数组的非常棒的例子。通常你会看到全零,但有时事情会变得很糟糕,你会看到其他数字。

    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,您将始终在打印输出中看到所有0s。如果取消同步块的注释,代码将运行而不会出错。

    【讨论】:

    • 您还可以通过在 arr 上同步增量和减量行来消除错误:pastebin.com/vN4E527P 这强调了这样一个事实,即唯一的线程不安全部分是这两行。
    • 有时我会得到一串随机数。我很困惑。你能解释一下工作吗?
    • 不应该 arr[i % arr.length]-- 和 arr[i % arr.length]++ 平衡,因为它正在执行相同的次数?换句话说,结果不应该总是为零吗?
    • @n0vi 是的,这就是为什么这是一个很好的例子,它是在多个线程上共享对象引起的问题。发生的情况是两个线程尝试同时增加和减少数组中的同一个项目,并且一个覆盖另一个,所以你看不到所有0
    • @iJee,没问题。很高兴为您提供帮助。
    猜你喜欢
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多