Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 跨对象实例同步_Java_Multithreading_Concurrency_Synchronized - Fatal编程技术网

Java 跨对象实例同步

Java 跨对象实例同步,java,multithreading,concurrency,synchronized,Java,Multithreading,Concurrency,Synchronized,我有一个物体转子,它有一个目标速度和一个电流速度。每个人都试图改变其当前速度以匹配设定的目标速度。我有4个转子运行4个独立的线程。控制器会定期为每个人分配一个新的目标速度 当我试图改变每个转子的电流速度时,我不能超过所有转子的电流速度之和而超过X值。总和(当前速度(转子1)+…+当前速度(转子2))!>十, 这是我的问题:当我检查是否可以提高转子的当前速度时,我会在速度总和条件下做一个if语句。然而,由于每个转子都是单独的螺纹,因此在检查之后,另一个转子可能会改变其值。因此,我在另一个线程中的签

我有一个物体转子,它有一个目标速度和一个电流速度。每个人都试图改变其当前速度以匹配设定的目标速度。我有4个转子运行4个独立的线程。控制器会定期为每个人分配一个新的目标速度

当我试图改变每个转子的电流速度时,我不能超过所有转子的电流速度之和而超过X值。总和(当前速度(转子1)+…+当前速度(转子2))!>十,

这是我的问题:当我检查是否可以提高转子的当前速度时,我会在速度总和条件下做一个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);
        }
    }
}

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

同步它们的最简单方法是使用
静态同步
方法

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

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()
之前等待解除锁定。

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

  • 在实例化
    转子之前,请按以下方式创建共享对象:

    对象锁定对象=新对象()

  • 公共转子(控制器c,int Y,int id)
    更改为
    公共转子(控制器c,int Y,int id,对象锁定对象)

  • 通过为所有
    转子添加相同的
    锁定对象
    实例,调用
    转子的构造函数
    ,您希望在它们之间同步转速变化

  • lockObject
    存储为构造函数主体中转子的实例字段

  • 转子
    中,使用
    锁定对象
    以以下方式进行同步:

示例代码:

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

他不能从静态方法访问实例属性。@Kayaman但是他可以在参数中传递实例,然后访问私有方法,甚至是所传递实例的私有成员。如果他改变设计,当然可以。