gpt4 book ai didi

Java多线程的synchronized问题

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:47:31 25 4
gpt4 key购买 nike

我只学了wait()notify()或者notifyAll(),所以要用这个函数来控制程序.

这个程序有多个线程,分别打印一些消息集,但我不能在特定线程运行时阻塞其他线程。

我找到了很多方法,但我完全不明白。我的代码如下。

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 boolean 变量让其他线程在特定线程执行期间等待。

我真的很想得到消息不混杂的正常结果。

但是我的结果是这样的。

LeftSideCar: Approaching...

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

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

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

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

+一些具体信息以供理解

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 类是感知左右车移动的传感器。

因为是实时系统,所以是并发执行的,在java中可以用线程来表示。

此外,Direction 函数是重写函数,如下所示。

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() 方法的实现相关的非常基本的缺陷。在继续解决问题之前,让我们看看这些方法实际上是如何工作的。

了解 wait() 和 notify(): wait()notify() 都是对象级 API。它适用于当前正在处理该对象的线程。因此,等待列表是在每个对象级别而不是线程级别维护的。考虑以下示例:

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 的等待列表中。其他线程也是如此。

现有代码的问题:需要进行多项改进:

  1. 通过运行方法同步:不需要这种同步,因为每个线程都有自己的运行实现,并且不会共享该线程对象。
  2. boolean 变量锁:直接 boolean 变量不是保持同步的好选择,因为当多个线程处理它时,它们可能会导致一致性问题。
  3. wait() 方法: 这才是真正的问题所在。这里我们有两个对象,一个是 LeftRightCar,另一个是 FrontCar。因此,当为 LeftRightCar 调用 wait() 时,线程被添加到 LeftRightCar 对象的等待队列中。当为FrontCar调用时,线程被添加到FrontCar对象的等待队列中。因此,在实际的 wait()notify() 中,对不同对象的调用将无济于事。

解决方案:

wait()notify() 应该在一些公共(public)对象而不是这些类对象上调用。所以,下面的代码应该可以工作:

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

关于Java多线程的synchronized问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50187531/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com