当前位置: 首页 > 面试题库 >

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

康言
2023-03-14
问题内容

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

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

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

synchronized (array1[]){

}

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

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

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

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

synchronized (array1[i][j]){

}

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


问题答案:

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

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

public void myMethod() {

    unsynchronized_statements...

    synchronized(myMonitorObject) {
        synchronized_statments...
    }

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

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

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

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

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

类:

  • 矩阵:细胞二维矩阵的表示
  • 单元格:矩阵单元格值的包装器
  • 操作:对单元格数组的抽象操作
  • IncrementOperation:增加每个像元值的操作
  • ReverseOperation:反转单元顺序的操作
  • 主要:应用程序

该应用程序在同一矩阵上启动多项操作。唯一的同步代码块在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()语句,以使同步执行和非同步执行之间的区别更加明显。



 类似资料:
  • 问题内容: 我创建了一个小型Java servlet,其目的很简单:调用它后,它将执行以下步骤: 从本地文件系统读取文件foo.json 处理文件中的数据并对其进行一些更改 将更改写回文件 代码的简化版: 现在,我面临一个问题,即可能有两个或多个对servlet的http请求几乎同时调用servlet。为了避免对同一文件进行多次并行写访问,我需要以某种方式进行同步。根据我对servlet生命周期过

  • 问题内容: 在什么情况下需要同步对实例成员的访问?我知道对类的静态成员的访问始终需要同步-因为它们在该类的所有对象实例之间共享。 我的问题是,如果不同步实例成员,什么时候会出现错误? 例如,如果我的课程是 在什么情况下(使用该类),我 需要 使用以下方法: 和 ? 预先感谢您的回答。 问题答案: 这取决于您是否希望类是线程安全的。大多数类都不是线程安全的(为简单起见),在这种情况下,您不需要同步。

  • 我对Java同步有一个疑问。我想知道如果我的类中有三个同步方法,一个线程在一个同步方法中获取锁,其他两个会被锁定吗?我问这个问题是因为我与以下语句混淆了。 当一个线程在一个对象的同步方法内部时,所有希望执行这个同步方法或该对象的任何其他同步方法的其他线程都必须等待。这个限制不适用于已经有锁并正在执行该对象的同步方法的线程。这样的方法可以调用该对象的其他同步方法而不会被阻塞。该对象的非同步方法当然可

  • 如何在将GUI保持为活动状态而不是Hibernate/等待状态的同时延迟进程或创建队列?

  • 更多面试题总结请看:【面试题】技术面试题汇总 基本概念 临界资源:一次仅允许一个进程使用的共享资源,也就是互斥资源 临界区:程序中访问临界资源的那段代码,也称危险区、敏感区 互斥:多个程序片段,同一时刻仅有一个能进入临界区 同步:若干程序片断运行必须严格按照规定的某种先后次序来运行。同步是一种更复杂的互斥:互斥不会限制程序对资源的访问顺序,即访问是无序的;而同步必须要按照某种次序来运行 临界区管理