java并发 - synchronized块

时间:2013-08-06 12:35:16

标签: java thread-synchronization

我的代码中存在一个不应该发生的线程问题 - 但是。所以我正在努力解决一些问题。我将尝试用简单的代码解释我的问题 - 因为我遇到问题的代码很复杂 所以简而言之:

...................
..................
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();
            }   
         }  
      }
   }

}

所以我担心这是否会起作用 - 我不知道锁中的对象是通过内存(需要是确切的对象)还是通过等于(实现相等)来比较

当static curentExecutingJob成员在第一个线程中有一个值对象并在其上创建锁定(在synchronized块中)并且第二个线程更改该值并尝试进入synchronized块时(我希望我希望是是线程2将继续执行,并且只有当它将从以前第一个线程获得它的DB获得相同的Job时才会阻塞它。)

我不知道这种方法是否可以完成且有意义

两个线程正在运行方法

中的以下代码
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停止在第3行从JVM执行,并且他的状态从运行变为runnable,并在轮询中设置为等待。

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

问题完成这个是两个线程正在使用不同的实例执行示例方法,因此同步整个方法都不会工作 - 我也有其他代码已在此方法中执行,我不希望它同步到
那么我的问题是否有解决方案 此外,如果我使同步(this.class){}它将失去多线程的好处和感觉

3 个答案:

答案 0 :(得分:1)

问题在于'currentExecutingJob'被定义为静态,这意味着ExecuteJob的所有实例共享该变量的相同“实例”。此外,您在同步块之外设置此变量的值,这意味着每个线程将以不受控制的方式设置它。您的以下同步块应该没有任何实际影响。

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

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

我的代码中没有看到任何内容。

答案 1 :(得分:0)

无法评论,所以我会把它作为答案。遗憾。

同步(curentExecutingJob)

将同步对象curentExecutingJob(用你的术语,内存)。如果使用currentExecutingJob.equals(otherExecutingJob)== true同步另一个对象otherExecutingJob,则两个synchronize语句不会相互影响。

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

答案 2 :(得分:0)

我看到你的代码检查工作状态,如果它已经准备好了,我认为这不是一种可行的方式

您可以使用Callable接口而不是Runnable

这是一个可以帮助您的详细示例。

Java Concurrency