小编典典

Java:如何同步数组访问以及在同步条件下进行的操作有哪些限制

java

我有一个2x2数组,有两个线程在运行。

是否可以在数组上的Java中使用同步语句?

锁定如何工作?Java教程线程说同步语句适用于对象,因此我不确定它们的含义。另一个网站说我可以像

synchronized (array1[]){

}

这是否同步对数组中所有内容的访问,以便将数组锁定到其他线程?

如果我有一个二维数组,我可以使用

synchronized (array1[i]) 锁定数组的行之一?

并可以用类似的东西锁定单个数组的值

synchronized (array1[i][j]){

}

但是,非常感谢您提供提示或帮助。其实我已经把它打开了,不管正确与否。但我想知道以备将来使用


阅读 237

收藏
2020-11-16

共1个答案

小编典典

是的,您可以使用数组作为监视对象进行同步,因为数组(甚至基元数组)都是Java中的对象。

您可以像这样在特定的监视器上同步代码块:

public void myMethod() {

    unsynchronized_statements...

    synchronized(myMonitorObject) {
        synchronized_statments...
    }

最佳实践是同步尽可能少的代码行。

在监视器上同步代码不会以任何方式影响监视器,它只会影响访问同步代码块的线程。在线程执行可以输入代码块之前,它必须在监视器上获得“锁”。Java运行时确保一次最多一个线程可以在监视器上拥有“锁”。
因此,在您的数组上进行同步并不会禁止未同步的代码块访问它! 诀窍是确保所有您不想同时发生的操作都在同一监视器上同步的块内。

由于Java不提供多维数组,仅提供数组数组,因此您当然可以在嵌套数组上进行同步以实现更细粒度的同步。如果将2d数组建模为行数组,则只能在行上同步,而不能在列上同步,因为在该示例中,列未表示为单独的数组。

如果它们不是非原始的,则只能对单个数组值进行同步,因此要使用Integer()而不是int。请注意,Integer()是不可变的对象,因此您将无法更改其值。一种解决方案是使用包含的数值的getter和setter创建自己的Cell()包装器对象。这将允许您让线程锁定单元格并安全地更改其值。

因为今天是我的休息日,所以我决定找点乐子,并创建了一个描述您所描述内容的有效示例。是的,这是我玩的想法。

类:

该应用程序在同一矩阵上启动多项操作。唯一的同步代码块在Operation类中。如果删除同步,则结果将是错误的,因为两个操作同时在操纵同一行。

同步时输出:

[105, 104, 103, 102, 101]
[110, 109, 108, 107, 106]
[115, 114, 113, 112, 111]
[120, 119, 118, 117, 116]
[125, 124, 123, 122, 121]
[130, 129, 128, 127, 126]
[135, 134, 133, 132, 131]
[140, 139, 138, 137, 136]
[145, 144, 143, 142, 141]
[150, 149, 148, 147, 146]

不同步时的示例输出:

[105, 4, 103, 102, 101]
[110, 9, 108, 207, 106]
[115, 14, 113, 212, 111]
[120, 19, 118, 217, 116]
[125, 124, 123, 122, 121]
[130, 129, 128, 127, 126]
[135, 34, 133, 232, 131]
[140, 139, 138, 137, 136]
[145, 144, 143, 142, 141]
[150, 149, 148, 147, 146]

请注意,我在操作实现中添加了一些Thread.sleep()语句,以使同步执行和非同步执行之间的区别更加明显。

2020-11-16