跨对象实例同步

时间:2017-01-26 19:28:49

标签: java multithreading concurrency synchronized

我有一个Rotor对象,它有一个goalSpeed和一个currentSpeed。每个人都试图改变其currentSpeed以匹配goalSpeed集。我有4个转子运行4个独立的螺纹。每个人都被控制器定期分配一个新的goalSpeed。

当我尝试在每个转子中改变其currentSpeed时,我不能超过所有转子的currentSpeed的总和超过X值。 sum(currentSpeed(Rotor1)+ ... + currentSpeed(Rotor2))!> X

这是我的问题:当我检查时,我可以增加转子的当前速度,我在速度总和条件上做出if语句。但是,有可能在此检查之后,因为每个转子是一个单独的螺纹,另一个转子的值会改变。因此,我在另一个帖子中的检查不再有效。我怎样才能确保当我在一个转子的setNewSpeed()方法时,没有其他转子会改变它的当前速度?

class Rotor implements Runnable {
    private int id;
    private int goalSpeed;
    private int currentSpeed;
    private Controller controller;
    private int Y;
    private int failedAttempts;
    private int successAttempts;
    private int maxSpeed;

    public int getSuccessAttempts() {
        return successAttempts;
    }

    public void setSuccessAttempts(int successAttempts) {
        this.successAttempts = successAttempts;
    }

    public int getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }

    public int getFailedAttempts() {
        return failedAttempts;
    }

    public Rotor(Controller c, int Y, int id){
        this.controller = c;
        this.Y = Y;
        this.id = id;
        this.currentSpeed = 0;
        this.failedAttempts = 0;
        this.goalSpeed = 0;
        this.maxSpeed = 0;
        this.successAttempts = 0;
    }

    synchronized public void setGoalSpeed(int s){
        this.goalSpeed = s;
    }

    public int getCurrentSpeed(){
        return currentSpeed;
    }

    synchronized private void setNewSpeed(){
        int currentDrain = 0;
        for(Rotor r : controller.getRotors()){
            currentDrain = currentDrain + r.getCurrentSpeed();
        }
        if((currentDrain + (goalSpeed - currentSpeed)) > 20){
            //we cannot increase by total amount because drain too high
            System.out.println("failed");
            this.failedAttempts++;
            currentSpeed = currentSpeed + (20 - currentDrain);
            System.out.println("currentSpeed:" + currentSpeed);
        } else {
            System.out.println("success");
            successAttempts++;
            currentSpeed = goalSpeed;
        }
//      System.out.println("goalSpeed:" + goalSpeed);
//      System.out.println("currentDrain:" + currentDrain);

}

    public void run() {
        try {
            while(true){
                setNewSpeed();
                if(currentSpeed > maxSpeed){
                    maxSpeed = currentSpeed;
                }

                Thread.sleep(Y);
            }   
        } catch (InterruptedException e) {
            System.out.println("Rotor " + id + ": checks=" + (int)(successAttempts + failedAttempts) + ", success rate=" + successAttempts + ", failedAttempts=" + failedAttempts + ", max=" + maxSpeed);
        }
    }
}

3 个答案:

答案 0 :(得分:1)

同步所有转子之间共享的锁。现在每个人都在自己的锁上进行同步(即this),所以即使该方法是同步的,也可以同时在不同的对象上调用它。

答案 1 :(得分:0)

同步它们的最简单方法是使用static synchronized方法。

也就是说,使用实例之间共享的显式锁对象可能是一种更好的方法。

答案 2 :(得分:0)

1)你不应该写

synchronized private void setNewSpeed()synchronized public void setGoalSpeed(int s)

private synchronized void setNewSpeed()public synchronized void setGoalSpeed(int s),如果您想尊重惯例和标准。

2)您在Rotor Runnable类中声明了两个同步方法,但这没有任何意义,因为在同步方法中,您不会操纵线程之间共享的数据。

3)您有多种方法可以解决您的问题 一个灵活的解决方案包括使用在线程之间共享的人工对象,并在调用setNewSpeed()方法时对此对象执行锁定。
它允许每个胎面在进入之前等待锁被删除setNewSpeed()

以下是实施解决方案的想法:

  • 在实例化Rotor之前,以这种方式创建共享对象:

    Object lockObject = new Object();

  • public Rotor(Controller c, int Y, int id)更改为public Rotor(Controller c, int Y, int id, Object lockObject)

  • 通过为所有Rotor添加相同的lockObject实例来调用Rotors的构造函数,您需要在它们之间进行速度更改。

  • lockObject存储为构造函数体中Rotor的实例字段。

  • Rotor中使用lockObject以这种方式进行同步:

示例代码:

 private void setNewSpeed(){
     synchronized(lockObject){
         ... your actual processing
      }
 }