나는 모든 정적 메소드가 자바 웹 애플리케이션의 맥락에서 synchronized
이어야한다고 말한 친구가있다. 그게 사실이야? 이것에 관한 많은 다른 스택 오버플로 페이지를 읽었습니다.Java : 모든 정적 메소드를 동기화해야합니까?
- 다중 스레드 (A Sevlet 컨테이너에서와 같이 스레드 풀과) 스레드 간의
- 공유 데이터, 여부
- 단일 클래스 로더 : 내가 믿게 한 것은 당신이 가지고있는 경우에만 동기화 할 필요가있다 세션 데이터 또는 정적 구성원 데이터입니다.
- 공유 데이터는 변경 가능해야합니다. 읽기 전용 데이터는 공유 할 수 있습니다.
정적 멤버가 동기화되어야하지만 정적 메서드가 아니라고 생각합니다.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadTest {
static String staticString = "";
// This static method is safe b/c it only uses local data.
// It does not use any shared mutable data.
// It even uses a string builder.
static String safeStaticMethod(String in) {
// This also proves that StringBuilder is safe
// When used locally by a thread.
StringBuilder sb = new StringBuilder();
sb.append("Hello: ");
sb.append(in);
return sb.toString();
}
// This static method is not safe b/c it updates and reads
// shared mutable data among threads.
// Adding synchronized will make this safe.
static String unsafeStaticMethod(String in) {
staticString = in;
StringBuffer sb = new StringBuffer();
sb.append("Hello: ");
sb.append(staticString);
return sb.toString();
}
public static void main(String[] args) {
ThreadTest test = new ThreadTest();
test.staticMethodWithLocalData();
test.staticMethodWithStaticData();
}
public void staticMethodWithLocalData() {
ExecutorService executor = Executors.newFixedThreadPool(2);
final int iterations = 100000;
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!safeStaticMethod("Thread1").equals("Hello: Thread1")) {
System.out.println("safeStaticMethod at " + index);
}
}
}
});
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!safeStaticMethod("Thread2").equals("Hello: Thread2")) {
System.out.println("safeStaticMethod at " + index);
}
}
}
});
}
public void staticMethodWithStaticData() {
ExecutorService executor = Executors.newFixedThreadPool(2);
final int iterations = 100000;
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!unsafeStaticMethod("Thread1").equals("Hello: Thread1")) {
System.out.println("unsafeStaticMethod at " + index);
}
}
}
});
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!unsafeStaticMethod("Thread2").equals("Hello: Thread2")) {
System.out.println("unsafeStaticMethod at " + index);
}
}
}
});
}
}
이 코드가 핵심을 증명합니까?
편집 : 이것은 내가 포인트를 증명하기 위해 해킹 한 일부 쓸데없는 코드입니다.
스레드 세이프 코드를 작성하는 것은 임의의 위치에서 '동기화 된'코드를 두드리는 것보다 훨씬 복잡합니다. – SLaks
버퍼로 쓰레드가 공유되지 않기 때문에'safeStaticMethod'는'StringBuffer'를 사용하여 여전히 안전합니다. 특정 메소드 호출에 국한됩니다. – Charlie
위의 내용을 자세히 설명하면 기본적으로 threadsafe 프로그램 작성에 보편적으로 유효한 "if X then Y"규칙은 없습니다. (대부분의 사람들은 불필요하게 응용 프로그램의 동시성을 줄입니다.) – millimoose