java 다중 루틴 (二) 공유 자원 경쟁 해결
1. 문제의 출현
/*
*
* canceled
* */
public abstract class IntGenerator {
private volatile boolean canceled = false;
public abstract int next();
public void cancel(){
canceled = true;
}
public boolean isCanceled(){
return canceled;
}
}
/*
* : , 【 】
* test() : 【 IntGenerator】
*/
public class EvenChecker implements Runnable {
private IntGenerator generator;
private final int id;
public EvenChecker(IntGenerator g, int id){ // Generator( )
generator = g;
this.id = id;
}
@Override
public void run() {
while( !generator.isCanceled() ){
int val = generator.next();
if(val %2 != 0){
System.out.println(val + " not even!");
generator.cancel();
}
}
}
// 【 IntGenerator】 EvenChcker
public static void test(IntGenerator gp, int count){
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < count; i++){
exec.execute(new EvenChecker(gp, i));
}
exec.shutdown();
}
public static void test(IntGenerator gp){
test(gp, 10);
}
}
// <span style="font-family:Arial, Helvetica, sans-serif;">Generator </span>
// java , ,
public class EvenGenerator extends IntGenerator {
private int currentEvenValue = 0;
@Override
public int next() {
++currentEvenValue; //
Thread.yield();
++currentEvenValue;
//currentEvenValue += 2;
return currentEvenValue;
}
public static void main(String[] args) {
EvenGenerator eg = new EvenGenerator();
EvenChecker.test(eg);
}
}
2.키워드synchronized를 사용하여 문제 해결만약synchronized로 표시된 방법에 대한 작업이 호출되고 있다면, 이 작업이 이 방법에서 되돌아오기 전에, 이 클래스에 표시된synchronized로 표시된 방법의 모든 호출이 막힐 것이다. 즉,
특정한 대상에 대해 그 모든synchronized 방법은 같은 자물쇠를 공유한다.
상례의 세 번째 단락 코드를 다음과 같이 바꾸면 프로그램은 영원히 정상 상태에 있고 끊임없이 짝수를 출력할 것이다
/*
* 1.synchronized ,
* 2. , synchronized
* 3. :synchronized private ,
* 4.
*/
public class EvenGenerator extends IntGenerator {
private int currentEvenValue = 0; // private ,
@Override
public synchronized int next() { // synchronized ,yield()
++currentEvenValue; //
Thread.yield();
++currentEvenValue;
//currentEvenValue += 2;
return currentEvenValue;
}
public static void main(String[] args) {
EvenGenerator eg = new EvenGenerator();
EvenChecker.test(eg);
}
}
2. 표시된 Lock 객체를 사용하여 문제 해결
/*
* synchronized EvenGenerator
* 1.Locks 、
* */
public class LockedEventGenerator extends IntGenerator{
private int currentEvenValue = 0;
private Lock lock = new ReentrantLock(); //
@Override
public int next() {
lock.lock(); //
try{
++currentEvenValue;
Thread.yield();
++currentEvenValue;
return currentEvenValue;
}finally{
lock.unlock(); //
}
}
public static void main(String[] args) {
EvenChecker.test(new LockedEventGenerator());
}
}
3.원자성
원자 조작은 라인 스케줄링 메커니즘에 의해 중단될 수 없는 조작을 가리킨다.
원자성은 더블과 롱을 제외한 모든 기본 유형의 읽기와 쓰기 작업에 적용될 수 있다
volatile 키워드로 롱이나 더블 유형의 변수를 수식할 때 원자성을 얻고,
비록 이것은synchronized와 유사한 효과가 발생할 수 있지만, 우리는volatile 키워드를 사용하는 것을 최대한 피하고synchronized로 전환해야 한다
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Exception in thread main java.lang. NoClassDefFoundError 오류 해결 방법즉,/home/hadoop/jarfile) 시스템은 Hello World 패키지 아래의class라는 클래스 파일을 실행하고 있다고 오인하여 시스템의 CLASSPATH 아래 (일반적으로 현재 디렉터리를 포함) Hell...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.