variables - 在线程之间共享数组安全吗?

标签 variables concurrency raku

像我在下面的代码中所做的那样,在 Promise 之间共享数组是否安全?

#!/usr/bin/env perl6
use v6;

sub my_sub ( $string, $len ) {
    my ( $s, $l );
    if $string.chars > $len {
        $s = $string.substr( 0, $len );
        $l = $len;
    }
    else {
        $s = $string;
        $l = $s.chars;
    }
    return $s, $l;
}

my @orig = <length substring character subroutine control elements now promise>;
my $len = 7;
my @copy;
my @length;
my $cores = 4;
my $p = @orig.elems div $cores;
my @vb = ( 0..^$cores ).map: { [ $p * $_, $p * ( $_ + 1 ) ] };
@vb[@vb.end][1] = @orig.elems;

my @promise;
for @vb -> $r {
    @promise.push: start {
        for $r[0]..^$r[1] -> $i {
            ( @copy[$i], @length[$i] ) = my_sub( @orig[$i], $len );
        }
    };
}
await @promise;

最佳答案

这取决于你如何定义“数组”和“共享”。就数组而言,有两种情况需要分别考虑:

  • 固定大小的数组(声明为my @a[$size]);这包括具有固定维度的多维数组(例如 my @a[$xs, $ys])。它们有一个有趣的特性,即支持它们的内存永远不需要调整大小。
  • 动态数组(声明为 my @a),按需增长。随着时间的推移,这些内存块实际上会随着内存的增长而使用。

就分享而言,也分为三种情况:

  • 这种情况是多个线程在其生命周期内接触数组,但由于某种并发控制机制或整体程序结构,一次只能有一个线程接触它。在这种情况下,从“使用数组的并发操作”的意义上讲,数组永远不会共享,因此不可能出现数据竞争。
  • 只读、非惰性情况。这是多个并发操作访问非惰性数组的地方,但只是为了读取它。
  • 读/写情况(包括当读取实际上导致写入时,因为数组已被分配了需要延迟计算的内容;请注意,对于固定大小的数组来说,这种情况永远不会发生,因为它们永远不会延迟)。

那么我们可以将安全性总结如下:

                     | Fixed size     | Variable size |
---------------------+----------------+---------------+
Read-only, non-lazy  | Safe           | Safe          |
Read/write or lazy   | Safe *         | Not safe      |

* 表示警告,虽然从 Perl 6 的角度来看是安全的,但您当然必须确保不会使用相同的索引执行冲突的操作。

总而言之,您可以安全地共享固定大小的数组并将其分配给来自不同线程的元素“没问题”(但要注意错误共享,这可能会让您为此付出沉重的性能损失)。对于动态数组,只有在共享期间才读取它们才是安全的,即使这样,如果它们不懒惰(尽管给定的数组分配大多是急切的,但您不太可能遇到这种情况)意外地)。由于操作不断增长,即使写入不同的元素,也会面临数据丢失、崩溃或其他不良行为的风险。

因此,考虑到原始示例,我们看到 my @copy;my @length; 是动态数组,因此我们不能在并发操作中写入它们。然而,这种情况发生了,所以可以确定代码不安全。

这里已经有的其他帖子很好地指出了更好的方向,但没有一个指出血淋淋的细节。

关于variables - 在线程之间共享数组安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43782864/

相关文章:

c++ - HTTP Server 3 示例中跨线程的 boost::asio 套接字共享

raku - Perl 6 : writable multidimensional subscript access with AT-POS

javascript - HTML5 地理定位当前 GPS 位置的纬度和经度坐标放入变量中

java - 需要在for循环中声明变量

python - 将字符串的可变大小部分保存到另一个变量

function - 使用百分号作为前缀运算符名称的一部分

raku - 如何将类方法作为参数传递给perl 6中类的另一个方法

variables - VHDL:变量和过程

c - nanosleep(),usleep()中产生CPU所需的最短时间量

Java同步问题