是的,您可以使用数组作为监视对象进行同步,因为数组(甚至基元数组)是 Java 中的对象。
您可以在特定监视器上同步代码块,如下所示:
public void myMethod() {
unsynchronized_statements...
synchronized(myMonitorObject) {
synchronized_statments...
}
最佳实践是同步尽可能少的代码行。
同步监视器上的代码不会以任何方式影响监视器,它只会影响访问同步代码块的线程。在线程执行进入代码块之前,它必须获得监视器上的“锁”。 Java 运行时确保一次最多有一个线程可以拥有监视器上的“锁”。因此,同步数组并不会禁止未同步的代码块访问它!诀窍是确保您不希望同时发生的所有操作都在同一监视器上同步的块内。
由于 Java 不提供多维数组,只提供数组的数组,因此您当然可以在嵌套数组上进行同步,以实现更细粒度的同步。如果将二维数组建模为行数组,则只能在行上同步,而不能在列上同步,因为在该示例中,列不表示为单独的数组。
如果这些值是非原始值,则只能同步单个数组值,因此使用 Integer() 而不是 int。请注意,Integer() 是一个不可变对象,因此您无法更改其值。解决方案是创建您自己的 Cell() 包装对象,并为所包含的数值提供 getter 和 setter。这将允许您让线程获得单元格的锁定并安全地更改其值。
因为今天是我的休息日,所以我决定找点乐子,并根据您的描述创建了一个工作示例。是的,这就是我的玩乐理念。
Classes:
-
Matrix:二维细胞矩阵的表示
-
Cell:矩阵单元值的包装
-
手术:对 Cell 数组的抽象操作
-
增量操作:增加每个单元格值的操作
-
反向操作:颠倒单元格顺序的操作
-
Main: 应用程序
应用程序在同一矩阵上启动多个操作。唯一的同步代码块位于类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() 语句,以使同步和非同步执行之间的差异更加明显。