简体   繁体   English

Java并发-同步块

[英]java concurrency - synchronized block

I have a thread issue in my code that should not be happening - but is. 我的代码中有一个线程问题,应该不会发生,但是确实如此。 So I'm trying to make some work around. 所以我正在努力解决。 I will try to explain my problems with simple code as I can - because the code that I'm experiencing the issue is big and complicated so in short the code: 我将尝试使用简单的代码来解释我的问题-因为我遇到的问题的代码又大又复杂,因此简而言之,代码是:

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

}

So my concern is if this going to work - I don know if the object in the lock is compared by memory(need to be the exact object) or by equals(to implement equal on it) 所以我担心的是这是否行得通-我不知道锁中的对象是通过内存(需要是确切的对象)还是通过equals(在其上实现equal)进行比较的

What happens when the static curentExecutingJob member has one value-object in first thread and creates lock on that(in synchronized block) and second thread changes that value and tries to enter synchronized block(My expectation that I'm hoping to be is that thread-2 will continue with executing and only time that it would be block is when he will get the same Job from DB that previously the first thread got it) 当静态curentExecutingJob成员在第一个线程中有一个值对象并在该线程上创建锁(在同步块中),而第二个线程更改该值并尝试进入同步块时会发生什么(我希望我是那个线程-2将继续执行,只有在他将从数据库获得与第一个线程先前相同的作业时,才会被阻塞)

I don't know if this approach can be done and has sense 我不知道这种方法是否可以做到并且有意义

Two thread are running the following code that is inside method 两个线程正在运行方法内部的以下代码

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    }

The ThreadA is stop from executing in line 3 from JVM and his state is changed from running to runnable and is set to wait in the poll. ThreadA停止从JVM的第3行执行,并且其状态从“运行”更改为“可运行”,并设置为在轮询中等待。

The ThreadB is given chance by the JVM and ThreadB executes lines 1, 2, 3, 4, 5, 6 that I don't want to happen. JVM给ThreadB一个机会,并且ThreadB执行我不想发生的第1、2、3、4、5、6行。 I want the first thread that enters the code in lines 2,3 to finish before someone from the rest threads have chances to enter the same code 我希望第2,3行中输入代码的第一个线程在其余线程中的某人有机会输入相同代码之前完成

Problem accomplish this is that the two threads are executing the example method with different instance so synchronized the whole method wont work - also I have other code that is been executed in this method and I don't want that to be synchronizing to 问题在于,这两个线程正在使用不同的实例执行示例方法,因此同步整个方法将无法工作-另外,我在该方法中执行了其他代码,并且我不希望将其同步到
So is there solution for my problem Also if I make synchronized(this.class){} it will lose the benefits and sense of multithreading 那么是否有解决我的问题的方法呢?如果我使synced(this.class){},它将失去多线程的好处和意义。

The problem is that the 'currentExecutingJob' is defined as static, meaning that all instances of ExecuteJob share the same 'instance' of this variable. 问题是“ currentExecutingJob”被定义为静态的,这意味着ExecuteJob的所有实例都共享此变量的相同“实例”。 In addition, you are setting the value of this variable outside of a synchronization block, which means that each thread will set it in an uncontrolled way. 此外,您正在同步块外部设置此变量的值,这意味着每个线程都将以不受控制的方式对其进行设置。 Your following synchronization block should have no practical impact whatsoever. 您随后的同步块应该没有任何实际影响。

Given the way your sample code is written, it appears to me that you don't need any static variables and you don't need any synchronization, as there are no resources shared across multiple threads. 考虑到示例代码的编写方式,在我看来您不需要任何静态变量,也不需要任何同步,因为没有多个线程共享资源。

However, Your comments in the code indicate that you want to prevent two threads from executing the same job at the same time. 但是,您在代码中的注释表明您要防止两个线程同时执行同一作业。 Your code does not achieve this, as there is no comparison of running jobs to see if the same job is running, and even if there was a comparison, your getJobsFromPath() would need to to construct a job list such that the same object instance would need to be reused when two threads/paths encounter the same 'job'. 您的代码无法实现这一点,因为没有正在运行的作业的比较来查看同一作业是否正在运行,即使进行了比较,您的getJobsFromPath()也需要构造一个作业列表,以使同一对象实例当两个线程/路径遇到相同的“作业”时,将需要重用。

I don't see any of this in your code. 我在您的代码中看不到任何信息。

Can't comment so I'll put it as an answer. 无法发表评论,因此我将其作为答案。 Sorry. 抱歉。

The block

synchronized(curentExecutingJob) 同步(curentExecutingJob)

will synchronize on the object curentExecutingJob (in your terms, memory). 将在对象curentExecutingJob(按照您的说法,内存)上同步。 If you synchronize on another object otherExecutingJob with currentExecutingJob.equals(otherExecutingJob) == true, both synchronize statements will not influence each other. 如果使用currentExecutingJob.equals(otherExecutingJob)== true在另一个对象otherExecutingJob上进行同步,则这两个同步语句将不会相互影响。

To your question/problem: It would be helpful if you describe what getJobsFromPath is doing or should do and what you actually want to do and what your problem actually is. 对于您的问题/问题:如果您描述getJobsFromPath在做什么或应该做什么,您实际想要做的事情以及您的实际问题是什么,将很有帮助。 It's not really clear to me. 对我来说还不是很清楚。

i saw your code that it check's for the status of job, if it is ready or not, well as i think this is not a afeasible way 我看到了您的代码,它检查工作状态(是否准备就绪),以及我认为这不是可行的方法

you can use the Callable Interface instead of Runnable 您可以使用Callable Interface代替Runnable

here is an example detailed which may help you. 这是一个详细的示例,可能会对您有所帮助。

Java Concurrency Java并发

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

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