Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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中的同步代码中以前发生的情况?_Java_Multithreading_Synchronization - Fatal编程技术网

如何防止java中的同步代码中以前发生的情况?

如何防止java中的同步代码中以前发生的情况?,java,multithreading,synchronization,Java,Multithreading,Synchronization,我只有一个同步方法。其目的是防止两个线程更新同一个表,这肯定会导致异常。我试图更新一个表,它的数据来自一个巨大的外部数据库。在更新我的表之前,我必须做一些过滤和清理,这需要很多时间。我创建了多个线程,以便可以划分任务并快速更新表。计划/设计是一个线程清理完数据后,它应该更新我的表,而其他线程仍在清理。然而,在我的示例代码中,线程正在覆盖这些值,因为关系发生在before之前。我不希望线程共享数据,我只希望它们在某些线程更新时不更新。如果您可以在下面的代码中看到,我已经创建了一个列表,我使用它来循

我只有一个同步方法。其目的是防止两个线程更新同一个表,这肯定会导致异常。我试图更新一个表,它的数据来自一个巨大的外部数据库。在更新我的表之前,我必须做一些过滤和清理,这需要很多时间。我创建了多个线程,以便可以划分任务并快速更新表。计划/设计是一个线程清理完数据后,它应该更新我的表,而其他线程仍在清理。然而,在我的示例代码中,线程正在覆盖这些值,因为关系发生在before之前。我不希望线程共享数据,我只希望它们在某些线程更新时不更新。如果您可以在下面的代码中看到,我已经创建了一个列表,我使用它来循环创建一个线程并传递列表中的每个数据。但是,结果是,线程1、4和5在同步方法中使用了相同的程序ID,而它们不应该使用。是否有人可以帮助防止这种情况,使每个线程在同步代码中都有一个唯一的Id

这是我的密码:

public Class HomeController{

    List<String> programList = new ArrayList<String>();
    programList.add("xxx");
    programList.add("yyy");
    for(String programId: programList){

    System.out.println("programId Controller is " + programId);
    //for each program Id create a thread
    runnable.setProgramId(programId);
    taskExecutor.execute(runnable);
    }

}

public class TestRunnable implements Runnable{

    public void run(){
            String threadName = Thread.currentThread().getName();
            System.out.println("threadName and programId Runnable are " + threadName +"--"+ programId);
            TestSynchronized testSynchronized = new TestSynchronized();
            testSynchronized.updateTable(programId);
            }
    }

}

public class TestSynchronized{

    private volatile boolean isLocked = false; 

    public synchronized void updateTable(String programId){

            while(isLocked) {
                 try {
                     wait();
                 } catch (InterruptedException e) {}
            }
            isLocked=true;
            String threadName = Thread.currentThread().getName();
            System.out.println("threadName and programId Synchronized are " + threadName +"--"+ programId);

            isLocked=false;
            notify();
    }
}

您有多少份
TestSynchronized
?如果它不止一个,您将无法获得任何同步


将同步与实际代码执行分开。

您有多少份
TestSynchronized
的副本?如果它不止一个,您将无法获得任何同步


将同步与实际代码执行分开。

您需要了解对象监视器是如何工作的<代码>同步将阻止对资源、对象引用的访问。在本例中,为每个线程创建一个新的
TestSynchronized
。由于同步工作在对象引用上,因此基本上不会在任何地方阻塞


如果创建一个
TestSynchronized
并将其传递给每个
TestRunnable
,您将获得预期的输出。

您需要了解对象监视器是如何工作的<代码>同步将阻止对资源、对象引用的访问。在本例中,为每个线程创建一个新的
TestSynchronized
。由于同步工作在对象引用上,因此基本上不会在任何地方阻塞


如果创建一个
TestSynchronized
并将其传递给每个
TestRunnable
,您将获得预期的输出。

显示的代码中有两个问题:

  • 您正在为每个线程重用相同的
    TestRunnable
    ,这意味着
    programmaid
    在使用之前会被覆盖(或可以被覆盖)
  • 您正在为每个线程创建一个新的
    TestSynchronized
    ,因此您根本没有线程安全性
  • 您需要做的是:

  • 创建一个,并且只创建一个
    TestSynchronized
  • 为每个程序ID创建一个新的
    TestRunnable
    。在构造函数中传递程序ID和共享的
    TestSynchronized

  • 显示的代码中有两个问题:

  • 您正在为每个线程重用相同的
    TestRunnable
    ,这意味着
    programmaid
    在使用之前会被覆盖(或可以被覆盖)
  • 您正在为每个线程创建一个新的
    TestSynchronized
    ,因此您根本没有线程安全性
  • 您需要做的是:

  • 创建一个,并且只创建一个
    TestSynchronized
  • 为每个程序ID创建一个新的
    TestRunnable
    。在构造函数中传递程序ID和共享的
    TestSynchronized
  • …由于发生在关系之前,线程正在覆盖值

    不是真的回答你的问题,但我认为你误解了“以前发生过”的含义

    Java语言规范(JLS)使用短语“之前发生”来描述某些保证,您可以使用这些保证来推理程序的行为。例如,JLS表示在一个线程中保留
    同步(o)
    块发生在另一个线程在同一对象上同步
    o
    之前。这就是为什么你知道如果线程A进入块,更新一些变量,然后离开块,然后线程B进入块;线程B保证查看变量中存储的线程A

    但它没有告诉你的是:

    它不会告诉您哪个线程将首先进入同步块。如果程序中的两个线程有可能同时在同一对象上尝试同步,那么就有了数据竞争。一条线会赢,另一条线会输,而且没有办法知道哪条线会赢

    如果您的程序中存在数据竞争,并且哪个线程获胜很重要,那么您就有一个缺陷

    您可以更改设计,使其与哪个线程获胜无关,也可以更改设计以使用某种更高级别的同步(队列、信号量、屏障等),以确保正确的线程获胜

    …由于发生在关系之前,线程正在覆盖值

    不是真的回答你的问题,但我认为你误解了“以前发生过”的含义

    Java语言规范(JLS)使用短语“之前发生”来描述某些保证,您可以使用这些保证来推理程序的行为。例如,JLS表示在一个线程中保留
    同步(o)
    块发生在另一个线程在同一对象上同步
    o
    之前。这就是为什么你知道如果线程A进入块,更新一些变量,然后离开块,然后线程B进入块;线程B保证查看变量中存储的线程A

    但这就是它的作用
    programId Controller is 23022490857
    programId Controller is 23022491963
    threadName and programId Runnable are taskExecutor-1--23022490857
    programId Controller is 23022492068
    threadName and programId Runnable are taskExecutor-2--23022491963
    programId Controller is 23022492300
    threadName and programId Synchronized are taskExecutor-1--23022491963
    programId Controller is 23022495561
    threadName and programId Runnable are taskExecutor-3--23022492068
    threadName and programId Synchronized are taskExecutor-2--23022492068
    programId Controller is 38416827134
    threadName and programId Synchronized are taskExecutor-3--23022492300
    threadName and programId Runnable are taskExecutor-4--23022492300
    threadName and programId Runnable are taskExecutor-1--38416827134
    threadName and programId Synchronized are taskExecutor-1--38416827134
    threadName and programId Runnable are taskExecutor-5--23022495561
    threadName and programId Synchronized are taskExecutor-4--38416827134
    threadName and programId Synchronized are taskExecutor-5--38416827134