通过使任务依赖于非任务对象来避免竞争条件

时间:2021-12-04 14:08:44

This question comes from section sharing resources of Think in java.

这个问题来自java中Think的资源共享部分。

Note that in this example the class that can be canceled is not Runnable. Instead, all the EvenChecker tasks that depend on the IntGenerator object test it to see whether it’s been canceled, as you can see in run( ).

请注意,在此示例中,可以取消的类不是Runnable。相反,依赖于IntGenerator对象的所有EvenChecker任务都会测试它是否被取消,正如您在run()中看到的那样。

And

For example, a task cannot depend on another task, because task shutdown order is not guaranteed. Here, by making tasks depend on a nontask object, we eliminate the potential race condition.

例如,任务不能依赖于另一个任务,因为不保证任务关闭顺序。在这里,通过使任务依赖于非任务对象,我们消除了潜在的竞争条件。

How to understand it?

怎么理解呢?

public abstract class IntGenerator {
  private volatile boolean canceled = false;
  public abstract int next();
  public void cancel() { canceled = true; }
  public boolean isCanceled() { return canceled; }
}

public class EvenChecker implements Runnable {
  private IntGenerator generator;
  private final int id;
  public EvenChecker(IntGenerator g, int ident) {
    generator = g;
    id = ident;
  }
  public void run() {
    while(!generator.isCanceled()) {
      int val = generator.next();
      if(val % 2 != 0) {
        System.out.println(val + " not even!");
        generator.cancel(); 
      }
    }
  }
  // ...
}

1 个解决方案

#1


1  

A race condition occurs when two or more tasks start parallel and, depending on which task comes first, cause your program to react differently, inexpectedly or even crash. Without appropriate precautions (ExecutorService, for example) you can't control the order entirely as the underlying operating system always is the last to decide then.

当两个或多个任务并行启动时会发生竞争条件,并且根据哪个任务首先出现,会导致程序以不同的方式做出反应,不可避免地甚至崩溃。如果没有适当的预防措施(例如ExecutorService),则无法完全控制订单,因为底层操作系统始终是最后决定的。

For example. Your have an

例如。你有一个

ArrayList<String> listA

and you have 3 independed Runnables.

你有3个独立的Runnables。

  • Runnable A is supposed to add 20 Strings to that list.
  • Runnable A应该在该列表中添加20个字符串。

  • Runnable B has to put them all to lower case.
  • Runnable B必须将它们全部放在小写字母中。

  • Runnable C drops duplicates.
  • Runnable C删除重复。

Starting them parallel would cause chaos.

并行启动它们会导致混乱。

Maybe the wanted order is given. Then the expected result will be a list with no duplicates and all Strings have lower case.

也许给出了所需的订单。然后预期的结果将是一个没有重复的列表,所有字符串都有小写。

But what if Runnable C comes first and even B is faster than A?

但是如果Runnable C排在第一位甚至B比A快?

Then your listA would neither be free from duplicates nor would your Strings be brought to lower case.

然后你的listA既不会重复,也不会将你的字符串改为小写。

This is what race condition is generally about. (put in simple words)

这就是竞争条件。 (用简单的话说)

So back to your example.

所以回到你的例子。

Would IntGenerator be a Runnable too, you'd surely have a lot of trouble to harmonize both Runnables to interact properly with each other. I wouldn't go that far to say that it is impossible, but troublesome.

IntGenerator也是Runnable,你必须要很好地协调两个Runnables才能相互正常交互。我不会那么说,这是不可能的,但很麻烦。

#1


1  

A race condition occurs when two or more tasks start parallel and, depending on which task comes first, cause your program to react differently, inexpectedly or even crash. Without appropriate precautions (ExecutorService, for example) you can't control the order entirely as the underlying operating system always is the last to decide then.

当两个或多个任务并行启动时会发生竞争条件,并且根据哪个任务首先出现,会导致程序以不同的方式做出反应,不可避免地甚至崩溃。如果没有适当的预防措施(例如ExecutorService),则无法完全控制订单,因为底层操作系统始终是最后决定的。

For example. Your have an

例如。你有一个

ArrayList<String> listA

and you have 3 independed Runnables.

你有3个独立的Runnables。

  • Runnable A is supposed to add 20 Strings to that list.
  • Runnable A应该在该列表中添加20个字符串。

  • Runnable B has to put them all to lower case.
  • Runnable B必须将它们全部放在小写字母中。

  • Runnable C drops duplicates.
  • Runnable C删除重复。

Starting them parallel would cause chaos.

并行启动它们会导致混乱。

Maybe the wanted order is given. Then the expected result will be a list with no duplicates and all Strings have lower case.

也许给出了所需的订单。然后预期的结果将是一个没有重复的列表,所有字符串都有小写。

But what if Runnable C comes first and even B is faster than A?

但是如果Runnable C排在第一位甚至B比A快?

Then your listA would neither be free from duplicates nor would your Strings be brought to lower case.

然后你的listA既不会重复,也不会将你的字符串改为小写。

This is what race condition is generally about. (put in simple words)

这就是竞争条件。 (用简单的话说)

So back to your example.

所以回到你的例子。

Would IntGenerator be a Runnable too, you'd surely have a lot of trouble to harmonize both Runnables to interact properly with each other. I wouldn't go that far to say that it is impossible, but troublesome.

IntGenerator也是Runnable,你必须要很好地协调两个Runnables才能相互正常交互。我不会那么说,这是不可能的,但很麻烦。