0

숙제는 모든 것이 적절해야하는 병렬 처리를 사용하여 프로젝트를 작성하는 것이 었습니다. 그러나 프로젝트를 만들었지 만 교수님이 내 코드에서 뭔가 잘못되었다고 언급했습니다. "배열 목록을 보시고, 뭔가 괜찮은지, 아마도 동기화가 아닌지 확인해주십시오."동기화 된 arraylist를 사용한 병렬 작업

커뮤니티에 저를 도울 것을 요청하고 잘못 될 수 있음을 지적하고 싶습니다. 나는 그것이 내 배열리스트를 괄호로 묶어서 synchronize을 덮지 않는 것이 문제라고 생각한다. 맞습니까? 내가 바로이 부분을 변경

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

    /** 
    * My project finds all dividors for specific number 
    *It must use threads, so I made them. First I start them (first loop) 
    *then join them (second loop). My project must have that loops. 
    *Problem might be with not synchronizing methods array list... 
    */ 

    public class Main { 

     private final static int NUMBER = 100; 
     private final static List<Integer> dividors = new ArrayList<Integer>(); 

     public static void main(String[] args) { 
      new Main().doStuff(); 
     } 
     private int sqr; 
     private int sqrp1; 

     private void doStuff() { 

      sqr = (int) Math.sqrt(NUMBER); 
      sqrp1 = sqr + 1; 

      Thread[] t = new Thread[sqrp1]; 

     //starting tasks 
      for (int i = 1; i < sqrp1; i++) { 
       final int it = i; 

       if (NUMBER % i == 0) { 
        final int e = i; 

        t[i] = new Thread(new Runnable() { 
         @Override 
         public void run() { 
          System.out.println("sta"+e); 
          if (!checkContains(e)) { 
           addElement(e); 
          } 

          final int dividednumber = NUMBER/e; 

          if (!checkContains(dividednumber)) { 
           addElement(dividednumber); 
          } 
         } 
        }); 
        t[i].start(); 
       } 
      } 

     //calling join for tasks 
      for (int i = 1; i < sqrp1; i++) { 
       final int it = i; 

       if (NUMBER % i == 0) { 
        try { 
         System.out.println("sto"+i); 
         t[i].join(); 
        } catch (InterruptedException ex) { 
         Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); 
        } 
       } 
      } 


      System.out.println("xxx"); 

      Collections.sort(dividors); 
      Integer[] arrayDividors = dividors.toArray(new Integer[0]); 

      for (int i = 0; i < arrayDividors.length; i++) { 
       System.out.println(arrayDividors[i]); 
      } 
     } 

     private synchronized void addElement(int element) { 
      dividors.add(element); 
     } 

     private synchronized boolean checkContains(int element) { 
      return dividors.contains(element); 
     } 
    } 

오전, 지금은 괜찮아?

t[i] = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     System.out.println("waiting " + e); 
     synchronized (this) { 
      System.out.println("entering " + e); 

      if (!checkContains(e)) { 
       addElement(e); 
      } 

      final int dividednumber = NUMBER/e; 

      if (!checkContains(dividednumber)) { 
       addElement(dividednumber); 
      } 
      System.out.println("leaving " + e); 
     } 
    } 
}); 
+0

BTW 조건에 'i <= sqrp1'을 써야합니다. 그렇지 않으면 제곱 숫자에 요인이 누락됩니다. 이 문제와 관련된 –

답변

1

이 작업을 단일 원자 작업으로 전환해야합니다.

if (!checkContains(dividednumber)) { 
    addElement(dividednumber); 
} 

두 개의 스레드가 있다고 가정 해보십시오. 하나 addElementWithoutDuplicates이있는 경우

T1: if (!checkContains(dividednumber)) { // false 
T2: if (!checkContains(dividednumber)) { // false 
T1:  addElement(dividednumber); // adds number 
T2:  addElement(dividednumber); // adds same number 

, 이런 일은 발생하지 않을 것이다.

+0

은 증가하는 카운터에서 얻은 두 스레드에 대해 'dividednumber'가 같아서는 안됩니다. 따라서 동일한 번호를 추가하는 것은 불가능할 것입니다. – Santosh

+0

@ 산 토슈 이론에서는 숫자가 두 번 더 추가 될 수 있지만 상한은이를 방지합니다. –

+0

괜찮지 만 checkContains가 동기화 되었습니까? 그것은이 코드를'synchronize (this) {...}'로 덮어야한다는 뜻인가요? – deadfish