Apache Ant 上并行的线程安全数学运算
Thread safe math operations in Parallel on Apache Ant
我是运行几个与Ant并行的子任务
这是build.xml的简化内容:
<target name="parallelOperations">
<var name="port.number" value="9006"/>
<for list="a,b,c,d,e" param="letter" parallel="true">
<sequential>
<echo>Letter @{letter}</echo>
<math result="port.number" operand1="${port.number}" operation="+" operand2="1" datatype="int"/>
<echo>${port.number}</echo>
</sequential>
</for>
</target>
这是主要结果:
[echo] Letter c
[echo] Letter b
[echo] Letter a
[echo] Letter d
[echo] Letter e
[echo] 9007
[echo] 9007
[echo] 9007
[echo] 9007
[echo] 9007
这里发生的是对于列表的每个元素,它打印元素的内容和加操作的结果。这里的问题是数学运算不是thread-save,意味着每个运算并发访问变量$port.number,加一个值,然后赋值。
有没有办法用 Ant 实现线程安全?我尝试做的是每个并行运行的子任务,获得一个唯一的端口号。如果有其他办法,应该也是不错的解决方法。
这是来自documentation of parallel
:
The primary use case for <parallel>
is to run external programs such as an application server, and the JUnit or TestNG test suites at the same time. Anyone trying to run large Ant task sequences in parallel, such as javadoc and javac at the same time, is implicitly taking on the task of identifying and fixing all concurrency bugs the tasks that they run.
因此同步操作取决于用户。可能有两种解决方案:
第一种方案比较简单,一般用于这种同步。
我将回答我自己的问题并发布具体解决方案,以防万一有人需要它。
这是可行的解决方案:
<target name="ParallelOperations">
<var name="port.number" value="9006"/>
<for list="a,b,c,d" param="letter" parallel="true">
<sequential>
<echo>Letter @{letter}</echo>
<!-- Synchronize the port number -->
<synchronized id="port.number.lock">
<echo>@{letter} new port ${port.number}</echo>
<var name="@{letter}.port.number" value="${port.number}" />
<math result="port.number" operand1="${port.number}" operation="+" operand2="1" datatype="int"/>
</synchronized>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
</sequential>
</for>
这是结果:
ParallelOperations:
[echo] Letter d
[echo] Letter a
[echo] Letter c
[echo] Letter b
[echo] c new port 9006
[echo] c 9006
[echo] b new port 9007
[echo] c 9006
[echo] c 9006
[echo] b 9007
[echo] c 9006
[echo] a new port 9008
[echo] b 9007
[echo] c 9006
[echo] b 9007
[echo] c 9006
[echo] a 9008
[echo] d new port 9009
[echo] c 9006
[echo] b 9007
[echo] a 9008
[echo] d 9009
[echo] b 9007
[echo] a 9008
[echo] d 9009
[echo] c 9006
[echo] a 9008
[echo] b 9007
[echo] d 9009
[echo] a 9008
[echo] b 9007
[echo] d 9009
[echo] a 9008
[echo] b 9007
[echo] d 9009
[echo] a 9008
[echo] d 9009
[echo] a 9008
[echo] d 9009
[echo] d 9009
根据@manouti 的回答,我从 Stefan Fanke 那里选择了同步命令,我使用每个字母创建一个特定变量来存储端口号。
如您所见,每个字母都分配有自己唯一的端口号。
我是运行几个与Ant并行的子任务
这是build.xml的简化内容:
<target name="parallelOperations">
<var name="port.number" value="9006"/>
<for list="a,b,c,d,e" param="letter" parallel="true">
<sequential>
<echo>Letter @{letter}</echo>
<math result="port.number" operand1="${port.number}" operation="+" operand2="1" datatype="int"/>
<echo>${port.number}</echo>
</sequential>
</for>
</target>
这是主要结果:
[echo] Letter c
[echo] Letter b
[echo] Letter a
[echo] Letter d
[echo] Letter e
[echo] 9007
[echo] 9007
[echo] 9007
[echo] 9007
[echo] 9007
这里发生的是对于列表的每个元素,它打印元素的内容和加操作的结果。这里的问题是数学运算不是thread-save,意味着每个运算并发访问变量$port.number,加一个值,然后赋值。
有没有办法用 Ant 实现线程安全?我尝试做的是每个并行运行的子任务,获得一个唯一的端口号。如果有其他办法,应该也是不错的解决方法。
这是来自documentation of parallel
:
The primary use case for
<parallel>
is to run external programs such as an application server, and the JUnit or TestNG test suites at the same time. Anyone trying to run large Ant task sequences in parallel, such as javadoc and javac at the same time, is implicitly taking on the task of identifying and fixing all concurrency bugs the tasks that they run.
因此同步操作取决于用户。可能有两种解决方案:
第一种方案比较简单,一般用于这种同步。
我将回答我自己的问题并发布具体解决方案,以防万一有人需要它。
这是可行的解决方案:
<target name="ParallelOperations">
<var name="port.number" value="9006"/>
<for list="a,b,c,d" param="letter" parallel="true">
<sequential>
<echo>Letter @{letter}</echo>
<!-- Synchronize the port number -->
<synchronized id="port.number.lock">
<echo>@{letter} new port ${port.number}</echo>
<var name="@{letter}.port.number" value="${port.number}" />
<math result="port.number" operand1="${port.number}" operation="+" operand2="1" datatype="int"/>
</synchronized>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
</sequential>
</for>
这是结果:
ParallelOperations:
[echo] Letter d
[echo] Letter a
[echo] Letter c
[echo] Letter b
[echo] c new port 9006
[echo] c 9006
[echo] b new port 9007
[echo] c 9006
[echo] c 9006
[echo] b 9007
[echo] c 9006
[echo] a new port 9008
[echo] b 9007
[echo] c 9006
[echo] b 9007
[echo] c 9006
[echo] a 9008
[echo] d new port 9009
[echo] c 9006
[echo] b 9007
[echo] a 9008
[echo] d 9009
[echo] b 9007
[echo] a 9008
[echo] d 9009
[echo] c 9006
[echo] a 9008
[echo] b 9007
[echo] d 9009
[echo] a 9008
[echo] b 9007
[echo] d 9009
[echo] a 9008
[echo] b 9007
[echo] d 9009
[echo] a 9008
[echo] d 9009
[echo] a 9008
[echo] d 9009
[echo] d 9009
根据@manouti 的回答,我从 Stefan Fanke 那里选择了同步命令,我使用每个字母创建一个特定变量来存储端口号。
如您所见,每个字母都分配有自己唯一的端口号。