몇 가지 멀티 스레드 취미 프로그램과 이전의 (공학/물리학) 연구에도 몇 편을 썼습니다. 그래서 나는 자신이 동기화/스레드 안전성 및 프리미티브, 평균 사용자가 JMM 및 여러 스레드 등을 사용하여 도전하고있는 것을 발견했습니다.Java : 스레드 공유 데이터를위한 프레임 워크
내가 필요한 것으로 발견되어 다른 스레드가 공유하는 클래스의 인스턴스 또는 정적 멤버를 표시하는 적절한 방법이 없습니다. . 그것에 대해 생각해보십시오. 우리는 개인/보호/공개와 같은 액세스 규칙과 getters/setter 및 많은 것을 명명하는 방법에 대한 규칙을 가지고 있습니다.
하지만 스레딩은 어떻게해야하나요? 변수를 스레드 공유로 표시하고 특정 규칙을 따르려면 어떻게해야합니까? 휘발성/원자 심판이 그 일을 할 수도 있지만 때로는 뮤텍스를 사용해야합니다. 그리고 수동으로 뭔가를 사용하는 것을 기억해야 할 때 ... 잊어 버릴 것입니다. :) - 어떤 시점에서.
나는 생각이 들었다. 나는 처음이 아니라는 것을 알았다. http://checkthread.org/example-threadsafe.html - 나중에 시도해 볼만한 꽤 괜찮은 코드 분석기가있는 것 같다. 필요.
그러나 처음 문제가 다시 발생합니다. 메시지 전달 프레임 워크보다 조금 더 낮은 레벨이 필요하고 원시 뮤텍스보다 조금 더 높은 레벨이 필요하다고 가정 해 봅시다 ... 우리는 ... 무엇을 가지고 있습니까?
기본적으로 내가 만든 것은 클래스 멤버를 공유 또는 비공유로 선언 할 수있게 해주는 일종의 순수 자바 슈퍼 프레임 워크입니다. 다음은
그것이 어떻게 사용될 수 있는지의 예입니다public final void transmit(final byte[] data) {
shared.run(new SharedRunnable<AllThreadsVars, Object, Object>() {
@Override
public Object run(final AllThreadsVars sharedVariable, final Object input) {
try {
if (sharedVariable.socket.isConnected() && sharedVariable.os != null) {
sharedVariable.os.write(data);
sharedVariable.os.flush();
}
} catch (final Exception e) { // Disconnected
setLastMessageAt(0);
}
return null;
}
}, null);
}
:
public class SimClient extends AbstractLooper {
private static final int DEFAULT_HEARTBEAT_TIMEOUT_MILLIS = 2000;
// Accessed by single threads only
private final SocketAddress socketAddress;
private final Parser parser;
private final Callback cb;
private final Heart heart;
private boolean lookingForFirstMsg = true;
private BufferedInputStream is;
// May be accessed by several threads (T*)
private final Shared<AllThreadsVars> shared = new Shared<>(new AllThreadsVars());
.
.
.
.
static class AllThreadsVars {
public boolean connected = false;
public Socket socket = new Socket();
public BufferedOutputStream os = null;
public long lastMessageAt = 0;
}
그리고 스레드 당신이 공유 객체에 대한 실행 가능한 같은 펑터를 전송해야 공유로 표시된 변수에 액세스 할 수
공유 실행 파일은 다음과 같이 정의됩니다.
어디로가는가? 글쎄,이 변수는 변수가 아니라 변수를 스레드 공유로 표시 할 수있는 도움을 준다. (예, 누출 될 수는 있지만 그 가능성은 낮다.) 일단 컴파일이 끝나면 컴파일 타임에이를 보장한다. 은 어떤 방법을 동기화하려면을 잊어 버릴 수 없습니다. 또한 컴파일 타임에 가능한 교착 상태를 찾기위한 테스트를 표준화하고 수행 할 수 있습니다 (단, 위의 프레임 워크로 컴파일 할 때 런타임에 구현 한 것만으로도 자바 컴파일러 이상을 필요로합니다).
기본적으로이 기능은 나에게 매우 유용하며 여기 바퀴를 다시 만들면이 기능이 제대로 작동하지 않을지 궁금해하고 있습니다. 그리고 나는 정말로 누구에게 물을 지 모릅니다. (오, 그래 및 공유 .RUN (는 SharedRunnable R, INPUT 입력) 단지이 그것이 정말 어떤 방법으로 완료되지 그래서 그냥 내 자신의 실험이다
private final <OUTPUT, INPUT> OUTPUT run(final SharedRunnable<SHARED_TYPE, INPUT, OUTPUT> r, final INPUT input) {
try {
lock.lock();
return r.run(sharedVariable, input);
} finally {
lock.unlock();
}
}
처럼 작동하지만 난 괜찮은 하나가 현재 프로젝트를 사용하고 있으며 실제로 많은 도움을줍니다.
여기에 질문이 있습니까? – Daniel
나는 당신의 예제를 이해하지 못한다고 생각하지만 ** 공유 변수 **는 동시성을 다룰 때 ** 당신이 원하지 않는 ** 것입니다. 잠금을 사용하는 공유 변수는 느리게 움직이고, 잠금 대기를 위해 더 많은 시간을 낭비하며, 일반적으로 응답이 적고 교착 상태에 빠지게합니다. 실제 동시성에 도달하는 가장 좋은 방법은 공유 상태가 전혀없는 것입니다. –
네,하지만 애플리케이션의 어느 시점에서 여러 개의 쓰레드가 필요하다면 메시지 큐 이건 다른 것이 든 공유 변수가 필요합니다. 내 아이디어는 임의의 원자와 비슷한 연산을 구성하는 방법을 갖는 것입니다 (중요 : 공유 표시 상태에서 컴파일 타임에 사용을 강제하는 것). 또한 모든 스레드가 표준화 된 프레임 워크를 사용하기 때문에 너무 많은 노력을 기울이지 않고 교착 상태 분석 도구를 작성할 수있었습니다. 나는 이것의 다소 단순한 변종을 이미 썼다. 그리고 내 코드에서 잠재적 인 교착 상태 장소를 감지 할 수 있었다. – gigurra