簡體   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