Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 2个线程同时访问一个同步函数_Java_Multithreading_Parallel Processing - Fatal编程技术网

Java 2个线程同时访问一个同步函数

Java 2个线程同时访问一个同步函数,java,multithreading,parallel-processing,Java,Multithreading,Parallel Processing,我有一个程序,它根据cpu的内核数自动生成线程(在我的例子中是2个,因为我在VM中运行该程序) 我有一个名为createTable的函数,它在不存在的情况下创建一个表,问题是我有多个线程,因此if语句可能无法使用,我尝试使用synchronized,但得到了相同的结果 public synchronized void createTable(Utils utils, String tableName, RowSerializable row) { if(!utils.getClient()

我有一个程序,它根据cpu的内核数自动生成线程(在我的例子中是2个,因为我在VM中运行该程序)

我有一个名为createTable的函数,它在不存在的情况下创建一个表,问题是我有多个线程,因此if语句可能无法使用,我尝试使用synchronized,但得到了相同的结果

public synchronized void createTable(Utils utils, String tableName, RowSerializable row) {
   if(!utils.getClient().tableExists(tableName)) {
       this.table = utils.generateTable(tableName, row);
       this.fieldsNames = utils.getNamesOfColumns(table);
   }
}

有什么想法吗

可能有两个线程正在访问
createTable
方法,我将尝试解释一下

此方法定义了
synchronized
,这意味着它所同步的对象是
This
。 所以我猜在您的程序中,两个线程可能会访问
createTable
,因为有两个不同的对象,每个
createTable
都是同步的

因此,如果两个线程想要创建具有相同名称的新表,那么这是可能的


注意:此分析基于您提供的信息,如果您认为不太可能,请提供更多信息,我将尽力提供帮助。

您可能会使用多个实例,否则您将不会在实例上同步的方法访问上出现同步问题。

为了解决您的问题,您可以在所有实例共享的静态字段上进行同步

在类中添加一个静态
对象
,并打开同步,应该可以解决并发访问的问题:

   public class YourClassThatHasTheProblem {
   ...
   private static final Object lock = new Object();
   ... 
    public void createTable(Utils utils, String tableName, RowSerializable row) {
      synchronized (lock) {
        if(!utils.getClient().tableExists(tableName)) {
          this.table = utils.generateTable(tableName, row);
          this.fieldsNames = utils.getNamesOfColumns(table);
         }
       }
  }
 ...
}

如果它不能解决您的问题,则意味着问题不仅仅来自代码同步,而是因为您在另一个类或方法中执行了类似的处理,而该处理与此调用不同步。因此,它通过调用
createTable()
创建了一个副作用。

您能提供更多详细信息吗?如果底层对象的同一实例在线程之间共享,那么同步方法就足够了。这是您的情况吗?您创建了多少包含此代码的对象?同步将在对象级别进行。如果每个线程创建一个单独的对象,则不会进行同步。是否从两个不同的对象调用该方法?如果在这种情况下为“是”,它将锁定两个不同的对象,因此将允许两个线程访问此方法代码。或者使用类级别锁。(使该方法为静态)该方法仅从一个对象@AndrewHenle调用,但从一个不是我的代码调用,我使用的是ApacheFlinkAPI@A.Vadillo你怎么知道它是同一个对象的实例?一个快速的测试是在一个静态对象上进行同步。这可以显示您所解释的内容,更详细地说(静态)它是同一个实例,因此两个线程都尝试创建表。第一个创建了它,第二个抛出了一个异常@AxelH——如果你是指我,我在发布它的第二天就删除了我的评论,因为你说的我也会猜,我更希望看到他如何在线程之间共享同一个实例失败。当然,静态字段很简单而且有效。我认为它有效!我会继续测试这个程序。Thanks@AxelH事实上,我理解,但我不确定OP是否真的知道创建竞争条件的资源是如何实例化的。如果解决方案有效,还可以帮助OP意识到他使用了多个实例,然后研究其代码以理解。@A.Vadillo如果对您有帮助,那就太好了:)@davidxxx完全同意您的观点。在最坏的情况下,这将有助于不需要参与这些实例初始化过程的读者。