繁体   English   中英

Java并发-同步块

[英]java concurrency - synchronized block

我的代码中有一个线程问题,应该不会发生,但是确实如此。 所以我正在努力解决。 我将尝试使用简单的代码来解释我的问题-因为我遇到的问题的代码又大又复杂,因此简而言之,代码是:

...................
..................
void createAndRunThreads(){
   List<Path> pathList = //read path from DB readPath();
   for(Path p : pathList){
      RunJob rj = new RunJob(p);
      Thred t = new Thread(rj);
      t.start();
   }
}

class RunJob implements Runnable {
   private Path path;
   private ExecuteJob execJob;

   public RunJob(Path path){
      this.path = path;
      this.execJob = new ExecuteJob();
   }

   public void run() {
      execJob.execute(path);
   }

}

class ExecuteJob {

   private static Job curentExecutingJob;

   public void execute(Path path){
      //here every thread should get different job list from others but this is not happening
      //so what happens eventually two threads are executing the same Job at once and it gets messy
      List<Job> jobList = getJobsFromPath(path);

      for(Job job : jobList) {
         curentExecutingJob=job;

         //work around that I'm trying to do. So if other thread tries to run the same job has to wait on lock(I dont know if this is posible do) 
         synchronized(curentExecutingJob){
            if(job.getStatus.equals("redy")){
               //do sum initialization 
               //and databese changes 
               job.run();
            }   
         }  
      }
   }

}

所以我担心的是这是否行得通-我不知道锁中的对象是通过内存(需要是确切的对象)还是通过equals(在其上实现equal)进行比较的

当静态curentExecutingJob成员在第一个线程中有一个值对象并在该线程上创建锁(在同步块中),而第二个线程更改该值并尝试进入同步块时会发生什么(我希望我是那个线程-2将继续执行,只有在他将从数据库获得与第一个线程先前相同的作业时,才会被阻塞)

我不知道这种方法是否可以做到并且有意义

两个线程正在运行方法内部的以下代码

1    Job j = getJobByIdFromDB(1111);
2    if(j.status.equals("redye")){
3        do staff
4        make database changes 
5        j.run();
6        j.state="running";
7    }

ThreadA停止从JVM的第3行执行,并且其状态从“运行”更改为“可运行”,并设置为在轮询中等待。

JVM给ThreadB一个机会,并且ThreadB执行我不想发生的第1、2、3、4、5、6行。 我希望第2,3行中输入代码的第一个线程在其余线程中的某人有机会输入相同代码之前完成

问题在于,这两个线程正在使用不同的实例执行示例方法,因此同步整个方法将无法工作-另外,我在该方法中执行了其他代码,并且我不希望将其同步到
那么是否有解决我的问题的方法呢?如果我使synced(this.class){},它将失去多线程的好处和意义。

问题是“ currentExecutingJob”被定义为静态的,这意味着ExecuteJob的所有实例都共享此变量的相同“实例”。 此外,您正在同步块外部设置此变量的值,这意味着每个线程都将以不受控制的方式对其进行设置。 您随后的同步块应该没有任何实际影响。

考虑到示例代码的编写方式,在我看来您不需要任何静态变量,也不需要任何同步,因为没有多个线程共享资源。

但是,您在代码中的注释表明您要防止两个线程同时执行同一作业。 您的代码无法实现这一点,因为没有正在运行的作业的比较来查看同一作业是否正在运行,即使进行了比较,您的getJobsFromPath()也需要构造一个作业列表,以使同一对象实例当两个线程/路径遇到相同的“作业”时,将需要重用。

我在您的代码中看不到任何信息。

无法发表评论,因此我将其作为答案。 抱歉。

同步(curentExecutingJob)

将在对象curentExecutingJob(按照您的说法,内存)上同步。 如果使用currentExecutingJob.equals(otherExecutingJob)== true在另一个对象otherExecutingJob上进行同步,则这两个同步语句将不会相互影响。

对于您的问题/问题:如果您描述getJobsFromPath在做什么或应该做什么,您实际想要做的事情以及您的实际问题是什么,将很有帮助。 对我来说还不是很清楚。

我看到了您的代码,它检查工作状态(是否准备就绪),以及我认为这不是可行的方法

您可以使用Callable Interface代替Runnable

这是一个详细的示例,可能会对您有所帮助。

Java并发

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM