클라이언트 요청의 흐름을 처리하려고합니다. 각 요청에는 특별한 유형이 있습니다. 먼저 해당 유형에 대한 일부 데이터를 초기화해야하며 이후에는 요청 처리를 시작할 수 있습니다. 클라이언트 유형이 처음 제공되면 해당 데이터를 초기화합니다. 이 후 해당 유형의 모든 요청은 해당 데이터를 사용하여 처리됩니다.이 코드는 스레드로부터 안전한 것입니까?
스레드로부터 안전한 방식으로이 작업을 수행해야합니다.
다음은 내가 작성한 코드입니다. 스레드로부터 안전합니까?
public class Test {
private static Map<Integer, Object> clientTypesInitiated = new ConcurrentHashMap<Integer, Object>();
/* to process client request we need to
create corresponding client type data.
on the first signal we create that data,
on the second - we process the request*/
void onClientRequestReceived(int clientTypeIndex) {
if (clientTypesInitiated.put(clientTypeIndex, "") == null) {
//new client type index arrived, this type was never processed
//process data for that client type and put it into the map of types
Object clientTypeData = createClientTypeData(clientTypeIndex);
clientTypesInitiated.put(clientTypeIndex, clientTypeData);
} else {
//already existing index - we already have results and we can use them
processClientUsingClientTypeData(clientTypesInitiated.get(clientTypeIndex));
}
}
Object createClientTypeData(int clientIndex) {return new Object();}
void processClientUsingClientTypeData(Object clientTypeData) {}
}
한 손에서 ConcurrentHashMap의은 map.put (A가 B) == 한편에서 동일한 A. null을 두 번, 과제 및 comparisson 조작 스레드 세이프되지 생산할 수 없다.
코드가 맞습니까? 그렇지 않은 경우 어떻게 수정해야합니까?
업데이트 : Martin Serrano는 코드가 스레드로부터 안전하며 이중 초기화 문제가 발생하지 않으므로 답변을 수락했습니다. 그러나 아래에 답변으로 게시 된 버전과 함께 발행물을 찾지 못했고 내 버전에는 동기화가 필요하지 않습니다.
'processClientUsingClientTypeData' 전에'else'가 필요하다고 생각합니다. – Gray
이것은 thread-safe도 아닙니다! 보세요 : 한 스레드가 get을 실행하고, null과 비교하고, if가 다른 스레드와 똑같은 경우 clientTypeData에 할당하고 결국 메서드에서 반환하지만 다른 스레드는 clientTypeData를 무시합니다. –
@Krzysztof 무엇이 안전하지 않습니까? 내가 말한 것처럼 _if_ 가끔씩 createClientTypeData를 두 번 이상 실행하는 것을 신경 쓰지 않아도된다. 설명하는 경우 두 번째 스레드가 첫 번째 스레드의 결과를 바꿉니다. 아마도 모든 요청이 초기화를 트리거 할 수 있기 때문에 매번 동일한 결과가 생성됩니다. 초기화가 _ 비싸다면, 더 복잡한 것을 피할 수 있습니다. –