자바 다 중 스 레 드 학습 의 잠 금 시 뮬 레이 션 과 피하 기(인 스 턴 스 설명)

1.자물쇠
잠 금 은 이러한 상황 입 니 다.여러 스 레 드 가 동시에 막 히 고 그들 중 하나 또는 모두 특정한 자원 이 방출 되 기 를 기다 리 고 있 습 니 다.스 레 드 가 무기한 으로 막 혀 있 기 때문에 프로그램 이 정상적으로 종 료 될 수 없다.
자바 잠 금 생 성 에 필요 한 네 가지 조건:
1.상호 배척 사용,즉 자원 이 하나의 스 레 드 에 의 해 사용(점유)되 었 을 때 다른 스 레 드 는 사용 할 수 없습니다.
2.선점 할 수 없고 자원 요구 자 는 자원 점유 자 에 게 서 자원 을 강제로 빼 앗 을 수 없 으 며 자원 은 자원 점유 자 에 의 해 자발적으로 방출 될 수 밖 에 없다.
3.요청 과 유지,즉 자원 요구 자가 다른 자원 을 요청 하 는 동시에 기 존 자원 에 대한 점 유 를 유지 하 는 것 이다.
4.순환 대기 열 이 존재 합 니 다.P1 은 P2 의 자원 을 차지 하고 P2 는 P3 의 자원 을 차지 하 며 P3 는 P1 의 자원 을 차지 합 니 다.이렇게 해서 대기 순환 도로 가 형성 되 었 다.
상술 한 네 가지 조건 이 모두 성립 될 때,바로 자물쇠 가 형성 된다.물론 자물쇠 가 잠 긴 상태 에서 상술 한 어떤 조건 을 깨 뜨리 면 자물쇠 가 사라 질 수 있다.
2.자물쇠 시 뮬 레이 션

package com.tl.skyLine.thread; 
 
import java.util.Date; 
 
/** 
 * Created by tl on 17/3/3. 
 */ 
public class DeadLock { 
 public static String bowl = " "; 
 public static String chopsticks = "  "; 
 
 public static void main(String[] args) { 
  LockA la = new LockA(); 
  new Thread(la).start(); 
  LockB lb = new LockB(); 
  new Thread(lb).start(); 
 } 
 
} 
 
 
class LockA implements Runnable { 
 public void run() { 
  try { 
   System.out.println(new Date().toString() + "          "); 
   while (true) { 
    synchronized (DeadLock.bowl) { 
     System.out.println(new Date().toString() + "       "); 
     Thread.sleep(3000); //       B      
     synchronized (DeadLock.chopsticks) { 
      System.out.println(new Date().toString() + "        "); 
      Thread.sleep(60 * 1000); //    ,       
     } 
    } 
   } 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
} 
 
class LockB implements Runnable { 
 public void run() { 
  try { 
   System.out.println(new Date().toString() + "          "); 
   while (true) { 
    synchronized (DeadLock.chopsticks) { 
     System.out.println(new Date().toString() + "        "); 
     Thread.sleep(3000); //       A      
     synchronized (DeadLock.bowl) { 
      System.out.println(new Date().toString() + "       "); 
      Thread.sleep(60 * 1000); //    ,       
     } 
    } 
   } 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
} 
결과:

Fri Mar 03 16:34:36 CST 2017           
Fri Mar 03 16:34:37 CST 2017         
Fri Mar 03 16:34:36 CST 2017           
Fri Mar 03 16:34:37 CST 2017        
결국 천정 천 학생 은 삼 젓가락 을 빼 앗 아 놓 지 않 았 습 니 다.추 보건 학생 은 그릇 을 빼 앗 았 습 니 다.죽어도 놓 지 않 았 습 니 다.하지만 젓가락 한 켤레 와 그릇 한 켤레 만 있 었 습 니 다.결국 둘 다 굶 어 죽 었 습 니 다.
3.고정 자물쇠 피하 기
만약 우리 가 천정 천 과 추 보건 학우 의 동료 라면 그들 이 굶 어 죽 는 것 을 차 마 볼 수 없 을 것 이다.그러면 어떻게 할 까?
우 리 는 사색 의 발생 을 피 하 는 방법 을 취해 야 한다.여기 서 두 가지 방법 을 소개 한다.하 나 는 잠 금 순서(스 레 드 는 일정한 순서에 따라 잠 금)이다.다른 하 나 는 잠 금 시한 을 추가 하 는 것 이다.
3.1 잠 금 추가 순서
여러 스 레 드 가 같은 자 물 쇠 를 필요 로 하지만 서로 다른 순서에 따라 자 물 쇠 를 추가 하면 자물쇠 가 쉽게 발생 한다.모든 스 레 드 가 같은 순서 로 자 물 쇠 를 얻 을 수 있다 면 잠 금 은 일어나 지 않 을 것 이다.우리 위의 코드 는 자 물 쇠 를 모 의 하기 위해 스 레 드 LockA 와 LockB 두 동료의 자원 쟁탈 순 서 를 조정 했다.LockA 는 먼저 그릇 을 빼 앗 은 다음 에 sleep 3 초 동안 LockB 는 먼저 젓가락 을 빼 앗 았 다.우 리 는 지금 자원 쟁탈 순 서 를 바 꾸 었 다.두 스 레 드 는 모두 먼저 그릇 을 빼 앗 고 젓가락 을 빼 앗 으 며 이 순서에 따라 엄 격 히 운행 한다.그러면 A 가 그릇 을 빼 앗 은 후에 B 는 자원 을 쟁탈 한다.그릇 을 빼 앗 는 것 부터 시작 해 야 한다.그릇 을 빼 앗 지 못 하 는 상황 에서 젓가락 을 빼 앗 으 면 자물쇠 가 생기 지 않도록 하 는 것 도 자물쇠 가 생기 지 않도록 하 는 가장 간단 한 방법 이다.
코드 수정 은 다음 과 같 습 니 다.

/** 
 * Created by tl on 17/3/3. 
 */ 
public class UnDeadLock { 
 public static String bowl = " "; 
 public static String chopsticks = "  "; 
 
 public static void main(String[] args) { 
  LockA la = new LockA(); 
  new Thread(la).start(); 
  LockB lb = new LockB(); 
  new Thread(lb).start(); 
 } 
 
} 
 
 
class LockA implements Runnable { 
 public void run() { 
  try { 
   System.out.println(new Date().toString() + "          "); 
   while (true) { 
    synchronized (UnDeadLock.bowl) { 
     System.out.println(new Date().toString() + "       "); 
     synchronized (UnDeadLock.chopsticks) { 
      System.out.println(new Date().toString() + "        "); 
     } 
    } 
    Thread.sleep(5000); 
   } 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
} 
 
class LockB implements Runnable { 
 public void run() { 
  try { 
   System.out.println(new Date().toString() + "          "); 
   while (true) { 
    synchronized (UnDeadLock.bowl) { 
     System.out.println(new Date().toString() + "       "); 
     synchronized (UnDeadLock.chopsticks) { 
      System.out.println(new Date().toString() + "        "); 
     } 
    } 
    Thread.sleep(5000); 
   } 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
} 
실행 결과

Fri Mar 24 11:16:51 CST 2017           
Fri Mar 24 11:16:51 CST 2017           
Fri Mar 24 11:16:51 CST 2017        
Fri Mar 24 11:16:51 CST 2017         
Fri Mar 24 11:16:51 CST 2017        
Fri Mar 24 11:16:51 CST 2017         
Fri Mar 24 11:16:56 CST 2017        
Fri Mar 24 11:16:56 CST 2017         
Fri Mar 24 11:16:56 CST 2017        
Fri Mar 24 11:16:56 CST 2017         
Fri Mar 24 11:17:01 CST 2017        
Fri Mar 24 11:17:01 CST 2017         
다 시 는 자물쇠 가 잠 겨 있 지 않 을 겁 니 다.
3.2 잠 금 시효
잠 금 시 효 를 가 하 는 원 리 는 모든 방문 스 레 드 에 접근 시 효 를 증가 시 키 는 것 이다.만약 에 한 스 레 드 가 주어진 기한 내 에 필요 한 모든 자 물 쇠 를 성공 적 으로 얻 지 못 하면 이미 얻 은 자 물 쇠 를 되 돌려 주 고 풀 어 주 는 것 이다.
이 목 표를 실현 하기 위해 서 우 리 는 표 시 된 잠 금 을 사용 하지 않 고 신 호 량 Semaphore 로 제어 합 니 다.신 호 량 은 자원 이 얼마나 많은 스 레 드 에 접근 할 수 있 는 지 를 제어 할 수 있 습 니 다.여기 서 우 리 는 하나의 스 레 드 에 만 접근 할 수 있 고 비슷 한 잠 금 을 할 수 있 습 니 다.그리고 신 호 량 은 시간 초과 시간 을 지정 할 수 있 습 니 다.우 리 는 이 시간 초과 에 따라 추가 처 리 를 할 수 있 습 니 다.성공 적 으로 얻 을 수 없 는 경우 에는 반복 적 으로 시도 하거나 시도 횟수 를 지정 하거나 바로 종료 할 수 있 습 니 다.

package com.tl.skyLine.thread; 
 
import java.util.Date; 
import java.util.concurrent.Semaphore; 
import java.util.concurrent.TimeUnit; 
 
/** 
 * Created by tl on 17/3/3. 
 */ 
public class UnDeadLock { 
 public static String bowl = " "; 
 //                   
 public static final Semaphore a1 = new Semaphore(1); 
 public static String chopsticks = "  "; 
 //                    
 public static final Semaphore a2 = new Semaphore(1); 
 
 public static void main(String[] args) { 
  LockAa la = new LockAa(); 
  new Thread(la).start(); 
  LockBa lb = new LockBa(); 
  new Thread(lb).start(); 
 } 
 
} 
 
 
class LockAa implements Runnable { 
 public void run() { 
  try { 
   System.out.println(new Date().toString() + "          "); 
   while (true) { 
    if (UnDeadLock.a1.tryAcquire(1, TimeUnit.SECONDS)) { 
     System.out.println(new Date().toString() + "       "); 
     if (UnDeadLock.a2.tryAcquire(1, TimeUnit.SECONDS)) { 
      System.out.println(new Date().toString() + "        ,     ,    "); 
      Thread.sleep(60 * 1000 * 10); //          ,        
     } else { 
      System.out.println(new Date().toString() + "        ,        "); 
     } 
    } else { 
     System.out.println(new Date().toString() + "       ,       "); 
    } 
 
    UnDeadLock.a1.release(); //    
    UnDeadLock.a2.release(); 
    System.out.println(new Date().toString() + "                "); 
    Thread.sleep(1000); //       ,     do something      
   } 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
} 
 
 
class LockBa implements Runnable { 
 public void run() { 
  try { 
   System.out.println(new Date().toString() + "          "); 
   while (true) { 
    if (UnDeadLock.a2.tryAcquire(1, TimeUnit.SECONDS)) { 
     System.out.println(new Date().toString() + "        "); 
     if (UnDeadLock.a1.tryAcquire(1, TimeUnit.SECONDS)) { 
      System.out.println(new Date().toString() + "       ,     ,    "); 
      Thread.sleep(60 * 1000 * 10); //          ,        
     } else { 
      System.out.println(new Date().toString() + "       ,       "); 
     } 
    } else { 
     System.out.println(new Date().toString() + "        ,        "); 
    } 
 
    UnDeadLock.a1.release(); //    
    UnDeadLock.a2.release(); 
    System.out.println(new Date().toString() + "                "); 
    Thread.sleep(10 * 1000);//        ,  tryAcquire  1 ,  B  A        ,          
   } 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
} 
결실

Fri Mar 03 18:12:07 CST 2017           
Fri Mar 03 18:12:07 CST 2017           
Fri Mar 03 18:12:07 CST 2017        
Fri Mar 03 18:12:07 CST 2017         
Fri Mar 03 18:12:08 CST 2017        ,         
Fri Mar 03 18:12:08 CST 2017                 
Fri Mar 03 18:12:08 CST 2017       ,     ,     
Fri Mar 03 18:12:10 CST 2017       ,        
Fri Mar 03 18:12:10 CST 2017                 
Fri Mar 03 18:12:11 CST 2017        
Fri Mar 03 18:12:11 CST 2017        ,     ,     
분명히 볼 수 있 듯 이 우 리 는 자 물 쇠 를 만족 시 키 는 세 번 째 조 를 깨 뜨 렸 다.즉,자원 요구 자가 다른 자원 을 요구 하 는 동시에 기 존의 자원 에 대한 점 유 를 유지 하고 그릇 과 젓가락 을 완전히 빼 앗 지 못 했 을 때 두 사람(스 레 드)은 모두 차지 하 는 자원 을 방출 하여 자원 을 쟁탈 하기 시작 했다.이렇게 한 사람 이 그릇 과 젓가락 을 빼 앗 은 후에 배 불리 먹고 다른 사람 에 게 먹 인 다.이렇게 해서 당신 은 성공 적 으로 당신 의 두 동 료 를 구 했 습 니 다!
Semaphore api:

acquire 
 
public void acquire() 
    throws InterruptedException 
 
            ,               ,       。      (       )     ,         1。 
 
          ,             ,                        : 
 
                release()   ,                   ;   
              。 
 
       : 
 
                 on ;   
           。 
 
     InterruptedException,              。 
 
   : 
  InterruptedException -           
 
release 
 
public void release() 
 
       ,        。      ,          1。            ,                   。            (    )   。 
 
                  acquire()      。                       。 
wait()와 sleep()의 차이 점:
sleep()방법 은 CPU 만 내 주 었 을 뿐 동기 자원 잠 금 을 풀 지 않 습 니 다!!
wait()방법 은 현재 스 레 드 가 동기 화 자원 자 물 쇠 를 잠시 양보 하여 이 자원 을 기다 리 고 있 는 다른 스 레 드 가 이 자원 을 얻 고 실 행 될 수 있 도록 하 는 것 을 말한다.
이상 의 자바 다 중 스 레 드 학습 의 잠 금 시 뮬 레이 션 과 피(인 스 턴 스 설명)는 바로 작은 편집 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.여러분 께 참고 가 되 고 저희 도 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기