> Java > java지도 시간 > Java 스레드 안전성 및 동기화 예시 분석

Java 스레드 안전성 및 동기화 예시 분석

WBOY
풀어 주다: 2023-04-29 20:58:05
앞으로
854명이 탐색했습니다.

스레드 안전성 문제

여러 스레드가 동일한 리소스를 공유(액세스)할 수 있습니다.

예를 들어 동일한 개체, 동일한 변수, 동일한 파일에 액세스합니다.

여러 스레드가 동일한 리소스에 액세스하면 데이터 혼란이 발생하기 쉽습니다. 스레드 안전 문제라고 불리는 데이터 보안 문제

어떤 상황에서 스레드 안전 문제가 발생합니까?

여러 스레드가 동일한 리소스를 공유합니다

그리고 적어도 하나의 스레드가 쓰기 작업을 수행합니다

예:

돈 입금 및 인출 돈 문제

입금 쓰레드와 출금 쓰레드가 각각 2개가 있습니다

입금 출금 쓰레드 1 잔액 쓰레드 2
1000 "----1000------" 1000
1000+1000--- - -》2000
                                                                                                                                 티켓 판매
스레드 1 투표 수 스레드 2

1000 «----1000------» 1000
1000-1------»999

999 «------1000 -1

정확함 : end 최종 잔액은 999가 아닌 998이어야 합니다

티켓 구매 문제 오류(스레드 동기화되지 않음) 예:
public class love implements Runnable{
    private int piao=3000;//有3000张票
    public boolean sale() {//ture代表还有票;false代表没有票了
        if(piao<1) return false;
         piao--;//卖1张票
         
         //细化piao--;
         //寄存器=piao;
         //寄存器=寄存器-1;
         //piao=寄存器;
         
         String sk =Thread.currentThread().getName();//获取当前线程(买票窗口)的名字
         System.out.println(sk+"卖了1张票,还剩下"+piao+"张");
         return piao>1;
    }
    public void run() {
         while(sale());//循环执行;直至卖完票返回false
    }
}
 
public class Main {
    public static void main(String[] a) {
        love tjlove =new love();
        for(int i=1;i<=4;i++) {//循环4次;产生4个线程(窗口)卖票
            Thread tj = new Thread(tjlove());
            tj.setName(""+i);
            tj.start();
        }
    }
}
로그인 후 복사

부분 출력 결과:



스레드 안전 문제

분석 문제

클래스 1 변수 값의 스레드 A와 B는 +1 연산에 대해 17입니다

최종 결과는 2 18

Solution

Java 스레드 안전성 및 동기화 예시 분석잠금:

프로세스: 먼저 스레드 A가 이 17에 먼저 액세스한 다음 잠그고 +를 입력합니다. 1을 읽은 후 작업이 18

으로 변경되고 잠금 기간 동안 다른 스레드에서 17에 접근할 수 없습니다
변경이 완료된 후 쓰고 17을 잠금 해제합니다.
그런 다음 스레드 B가 접근하고 다시 잠그고 반복합니다. 위의 작업은 다시 잠금을 해제합니다

이렇게 하면 하나의 스레드만 동시에 액세스할 수 있으므로 안전이 보장됩니다. 이전 오류는 이러한 스레드가 함께 액세스했기 때문이었습니다.

스레드 동기화
방금 언급한 잠금 작업 스레드 동기화 기술

스레드 동기화 기술은 스레드 안전 문제를 해결하는 데 사용할 수 있습니다


스레드 동기화에는 Java의 두 가지 방법이 있습니다:

1. 동기화 문

2. 동기화 방법

동기화 문

public class love implements Runnable{
	private int piao=3000;//本人cpu单核性能过强,数据量大些才能看到是4个线程在卖票
	public boolean sale() {
		synchronized(this) {//1个线程获取这个对象的锁,并加锁;    synchronized作用于整个语句
		//this指向当前对象
		//不能用new Object();这样会产生新的对象,产生新的锁
		//把this换成"123",效果基本一样;因为其存在常量值里,每次访问的对象一样
			if(piao<1) return false;
			piao--;
			String sk =Thread.currentThread().getName();
			System.out.println(sk+"卖了1张票,还剩下"+piao+"张");
			return piao>0;
			}
	}
	public void run() {
		 while(sale());
	}
}
로그인 후 복사

부분 출력 결과:

동기화(obj)의 원리

1. 각 개체에는 이와 관련된 고유 잠금(intrinsic lock) 또는 모니터 잠금(monitor lock)이 있습니다.

2. 동기화를 위한 첫 번째 실행문의 스레드입니다. obj의 내부 잠금을 획득하고 동기화 문에서 코드를 실행한 후 잠금을 해제할 수 있습니다

3. 하나의 스레드가 내부 잠금을 보유하고 있는 한 다른 스레드는 더 이상 동시에 이 잠금을 획득할 수 없습니다

✓ 이 잠금을 획득하려고 하면 BLOCKED 상태가 됩니다Java 스레드 안전성 및 동기화 예시 분석

4. 여러 스레드가 동일한 동기화(obj) 문에 액세스하는 경우

obj는 동기화를 달성하기 위해 동일한 개체여야 합니다

동기화 방법

public class love implements Runnable{
    private int piao=3000;
    public synchronized boolean sale() { //synchronized作用于整个方法
            if(piao<1) return false;
            piao--;
            String sk =Thread.currentThread().getName();
            System.out.println(sk+"卖了1张票,还剩下"+piao+"张");
            return piao>0;
    }
    public void run() {
         while(sale());
    }
}
로그인 후 복사
동기화할 수 없습니다. 생성자를 수정하세요

동기화 메서드의 본질

인스턴스 메서드: 동기화(this)

정적 메서드: 동기화(클래스 객체)

동기화 문은 동기 메서드보다 유연합니다.

동기화 문은 필요한 사항을 정확하게 제어할 수 있습니다. 추가 코드 범위를 잠그고 BLOCKED 상태의 스레드를 줄여 노동력을 최대한 활용하세요

스레드 동기화 기술을 사용한 후
스레드 안전성 문제는 해결되었으나 프로그램의 실행 효율성을 떨어뜨립니다

잠금으로 인해 사람들이 기다리게 됩니다. 스레드에는 추가 잠금 및 잠금 해제 작업이 있습니다

따라서 정말 필요할 때만 스레드 동기화 기술을 사용하세요

위 내용은 Java 스레드 안전성 및 동기화 예시 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:yisu.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿