Java多线程同步问题 [英] Java synchronized problems of multiple threads

查看:105
本文介绍了Java多线程同步问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只学习了wait()notify()notifyAll(),所以我必须使用此功能来控制程序.

I learned only wait() and notify() or notifyAll(), so I have to use this function to control of programs.

该程序具有多个线程,这些线程分别打印某些消息的集合,但是当特定线程正在运行时,我无法阻止其他线程.

This program has multiple threads which print set of some message individually, but I cannot block other thread while specific thread is running.

我有很多方法可以做,但是我完全不理解.我的代码在下面.

I find lots of way to do but I totally didn't understand. My code is below.

LeftRightCar.java:

public synchronized void run(){
    try{
        while(lock) wait();
        lock=true;
        System.out.println("LeftSideCar: "+left);
        state="Left";
        Direction();
        System.out.println("RightSideCar: "+right);
        state="Right";
        Direction();
        notifyAll();
        lock=false;
    }catch(InterruptedException e){
        e.printStackTrace();
    }
}

FrontCar.java:

public synchronized void run(){
    try{
        while(lock) wait();
        lock=true;
        System.out.println("frontCarVelocity: "+frontCarSpeed+": km/h");
        Direction();
        notifyAll();
        lock=false;
    }catch(InterruptedException e){
        e.printStackTrace();
    }
}

我正在使用lock布尔变量使其他线程在特定线程执行期间等待.

I'm using lock boolean variable to make other thread wait during execution of specific thread.

我真的很希望正常的结果是哪些消息没有混合.

但是我的结果是这样的.

But my result is like this.

LeftSideCar:接近...

LeftSideCar: Approaching...

frontCarVelocity:40:km/h方向:请勿踩左车道...

frontCarVelocity: 40: km/h Direction : Do not step on left lane...

方向:RightSideCar:正在接近...降低速度...方向

Direction : RightSideCar: Approaching... Decrease velocity...Direction

:请勿踩右车道... 80→70→60→50→40

: Do not step on right lane... 80 → 70 → 60 → 50 → 40

如何仅使用wait()notify()notifyAll()修复它?以上两个类是Sensor.java的子类,该子类具有lock布尔变量.

How can I fix it using only wait(), notify() or notifyAll()? Above two classes are children class of Sensor.java which has lock boolean variable.

+一些需要了解的特定信息

+some specific information for understanding

public class AutonomousCar {
public static void main(String[] args){
    FrontCar f=new FrontCar();
    LeftRightCar lr=new LeftRightCar();
    Thread Car[]={new Thread(f),new Thread(lr)};
    Car[0].start();
    Car[1].start();
}

AutonomousCar类表示具有可变传感器的汽车. FrontCar类是感应前车速度的传感器,而LeftRightCar类是感应左车和右车的运动的传感器.

AutonomousCar class means car which has variable sensors. FrontCar class is a sensor that sense the speed of front car and LeftRightCar class is a sensor that sense the moving of left and right car.

因为它是实时系统,所以它是并发执行的,可以由Java中的线程表示.

Because it is real-time system, it is concurrently executed which can be represented by threads in java.

此外,Direction功能是如下所示的替代功能.

Furthermore, Direction function is overriding function like below.

LeftRightCar.java的方向

public void Direction(){
    System.out.print("Direction : ");
    if(state.equals("Left")){
        if(left.equals("None")) System.out.println(message.get("None"));
        else if(left.equals("Approaching...")) System.out.println(message.get("Approaching-L"));
        else if(left.equals("Too close...")){
            System.out.println(message.get("Close-L"));
            isLeftClose=true;
        }
    }
    else if(state.equals("Right")){
        if(right.equals("None")) System.out.println(message.get("None"));
        else if(right.equals("Approaching...")) System.out.println(message.get("Approaching-R"));
        else if(right.equals("Too close...")){
            if(!isLeftClose) System.out.println(message.get("Close-R"));
            else System.out.println(message.get("Close-LR"));
        }
    }
}

FrontCar.java的方向

public void Direction(){
    System.out.print("Direction : ");
    if(frontCarSpeed==100){
        System.out.println(message.get("S"));
    }
    else if(speed<=frontCarSpeed){
        System.out.print(message.get("I"));
        while(speed<frontCarSpeed){
            System.out.print(speed+" → ");
            speed+=10;
        }
        System.out.println(speed);
    }
    else if(speed>frontCarSpeed){
        System.out.print(message.get("D"));
        while(speed>frontCarSpeed){
            System.out.print(speed+" → ");
            speed-=10;
        }
        System.out.println(speed);
    }
}

推荐答案

代码中有一个非常基本的缺陷,它与wait()和notify()方法的实现有关.在进行解决之前,让我们看看这些方法是如何工作的.

There is very basic flaw in the code which is related to implementation of wait() and notify() methods. Let's see how these methods actually works before proceeding to solution.

了解wait()和notify(): wait()notify()都是对象级API.它适用于当前在对象上运行的线程.因此,等待列表在每个对象级别而不是线程级别维护.考虑下面的示例:

Understanding wait() and notify(): Both wait() and notify() are object level APIs. It applies on threads that is currently working on the object. So, waiting lists are maintained at each object level instead of thread level. Consider below example:

public class Example{
  int counter = 0;

  synchronized void printCounter() throws Exception{
    notify();
    System.out.println(Thread.currentThread().getName() + "-->" + (counter++));
    wait();
  }

  public static void main(String[] args){
      Example example = new Example();
      Thread t1 = new MyThread(example);
      t1.setName("MyThread-1");
      Thread t2 = new MyThread(example);
      t2.setName("MyThread-2");
      t1.start();
      t2.start();
  }
}

class MyThread extends Thread{
    private Example obj = null;

    MyThread(Example obj){
        this.obj = obj;
    }

    public void run(){
        while(true){
            try{
                obj.printCounter();
                Thread.sleep(200);
            }catch(Exception ex){

            }
        }
    }
}

此示例有两个线程t1t2和一个对象example.我们为example对象调用了wait()notify(),因此,如果t1执行wait()语句,它将被添加到对象example的等待列表中.其他线程也是如此.

This example has two threads, t1 and t2 and one object example. We have called wait() and notify() for example object thus if t1 executes wait() statement, it will be added in waiting list for object example. Same goes with other threads.

现有代码存在的问题:有待改进的地方:

  1. 同步运行方法:不需要此同步,因为每个线程都有自己的运行实现,并且该线程对象不会共享.
  2. 布尔变量锁定:直接布尔变量不是保持同步的一个好选择,因为当多个线程对其进行操作时,它们可能是一致性问题.
  3. wait()方法::这是实际问题所在.在这里,我们有两个对象,一个是LeftRightCar,另一个是FrontCar.因此,当为LeftRightCar调用wait()时,线程将添加到LeftRightCar对象的等待队列中.并且当为FrontCar调用时,线程被添加到FrontCar对象的等待队列中.因此,在实际的wait()notify()中,对不同对象的调用将无济于事.
  1. Synchronization over run method: This synchronization won't be required as each thread will have its own implementation for run and that thread object won't be shared.
  2. boolean variable lock: Direct boolean variables are not a good option to maintain synchronization as their could be consistency issues when multiple threads are working on it.
  3. wait() method: This is where the actual problem lies. Here we have two objects, one of LeftRightCar and another of FrontCar. So, when wait() is called for LeftRightCar, thread is added in waiting queue of LeftRightCar object. And when it is called for FrontCar, thread is added in waiting queue of FrontCar object. So, in actual wait() and notify() calls for different objects won't help.

解决方案:

应该在某些公共对象而不是这些类对象上调用wait()notify().因此,以下代码应该可以工作:

The wait() and notify() should be called on some common object instead of these classes object. So, following code should work:

//lock is an instance of Object now, NOT a boolean variable
public void run(){ 
  synchronized(lock){
    lock.notifyAll();
    ...
    ...
    lock.wait();
  }
}

这篇关于Java多线程同步问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆