synchronized 를 이용 하여 스 레 드 동기 화 를 실현 하 는 사례 설명
11614 단어 synchronized스 레 드동기 화
(1)스 레 드 동기 화 정의:다 중 스 레 드 간 동기 화.
(2)다 중 스 레 드 동기 화 원인:하나의 다 중 스 레 드 프로그램 이 Runnable 인 터 페 이 스 를 통 해 이 루어 지면 클래스 의 속성 이 여러 스 레 드 에 의 해 공유 되 고 이 로 인해 자원 의 동기 화 문 제 를 야기 합 니 다.즉,여러 스 레 드 가 같은 자원 을 조작 하려 고 할 때 오류 가 발생 할 수 있 습 니 다.
(3)다 중 스 레 드 동기 화 를 실현 하 는 방식―동기 화 체 제 를 도입 한다.스 레 드 에서 하나의 자원 을 사용 할 때 자 물 쇠 를 추가 하면 다른 스 레 드 는 그 자원 에 접근 할 수 없고 자 물 쇠 를 풀 때 까지 방문 할 수 있다.이렇게 한 결과 모든 스 레 드 간 에 자원 경쟁 이 있 을 수 있 지만 모든 경쟁 자원 은 동기 화 되 고 갱신 되 며 동태 적 이 며 스 레 드 간 의 경쟁 으로 인해 자원 의'과도 한 소모'나'가상 소모'를 초래 하지 않 습 니 다.
위의 코드 는'과도 한 소모/가상 소모'문 제 를 구체 적 으로 보 여 줍 니 다.
public class TestTicketRunnable{
public static void main(String[] a){
TicketThread tThread = new TicketThread();
new Thread(tThread).start();
new Thread(tThread).start();
new Thread(tThread).start();
}
};
class TicketThread implements Runnable {
private int ticket = 5;
public void run(){
for (int i = 0; i < 5; i++){
if (ticket > 0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " :ticket = " + ticket--);
}
}
}
};
실행 결과:
Thread-0 :ticket = 5
Thread-2 :ticket = 5 //
Thread-1 :ticket = 4
Thread-1 :ticket = 2
Thread-2 :ticket = 3
Thread-0 :ticket = 3 //
Thread-0 :ticket = -1 //
Thread-1 :ticket = 1
Thread-2 :ticket = 0
위 에서 보 듯 이 표 는 모두 5 장 이 고 세 개의 스 레 드 가 표를 사 는 것 을 호출 했다.스 레 드 1 은 인터넷 에서 매 표 1 장 을 팔 았 고 이 어 스 레 드 2 오프라인 에서 도'첫 번 째'를 팔 아'가상 소모'문제 가 발생 했다.스 레 드 3 황소 당 은 마지막 1 장의 표를 팔 았 고 스 레 드 1 인터넷 에서 마지막 1 장 을 팔 았 다.'과도 한 소모'문제 가 발생 했다.이 두 가지 문 제 는 모두 실제 생활 에서 발생 할 수 없 는 것 이다.그러나 이 3 개의 스 레 드 집행 에서 발생 했다.그것 은 분명 문제 가 있 을 것 이다.문제 의 원인 은 바로 세 채널 의'매표원'이 한 채널 에서 일 을 하지 않 는 다 는 것 이다.또는 서로 동기 화 되 지 않 고 공 유 된 자원 이 없 기 때문에 이 문 제 를 야기 하 는 근본 적 인 원인 은 바로 상호 간 의 실현 방식 이 동기 화 되 지 않 는 것 이다.2.synchronized 를 사용 하여 동기 화 체 제 를 실현 합 니 다.
synchronized 키워드:자바 언어의 키 워드 는 대상 과 방법 또는 코드 블록 에 자 물 쇠 를 추가 할 수 있 습 니 다.하나의 방법 이나 코드 블록 을 잠 글 때 같은 시간 에 최대 하나의 스 레 드 만 이 코드 를 실행 할 수 있 습 니 다.
두 개의 병렬 스 레 드 가 같은 대상 object 의 이 잠 금 동기 코드 블록 에 접근 할 때 한 시간 동안 하나의 스 레 드 만 실 행 될 수 있 습 니 다.다른 스 레 드 는 현재 스 레 드 가 이 코드 블록 을 실행 한 후에 야 이 코드 블록 을 실행 할 수 있 습 니 다.
그것 은 두 가지 용법 을 포함한다.synchronized 방법 과 synchronized 블록 이다.
즉,스 레 드 간 동기 화 를 실현 하 는 방식 은 두 가지 가 있다.
① synchronized 동기 코드 블록 사용 하기;
② synchronized 키 워드 를 사용 하여 synchronized()를 만 드 는 방법
아래 는 각각 분석 하여 위 에서 표를 파 는 코드 를 개조 합 니 다.
① 코드―synchronized 동기 코드 블록 사용
class TicketThread implements Runnable {
private int ticket = 5;
public void run(){
for (int i = 0; i < 5; i++){
synchronized(this){
if (ticket > 0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " :ticket = " + ticket--);
}
}
}
}
}
② 코드―synchronized 키 워드 를 사용 하여 synchronized()방법 을 만 듭 니 다.
class TicketThreadMethod implements Runnable {
private int ticket = 5;
public void run(){
for (int i = 0; i < 5; i++){
this.sale();
}
}
public synchronized void sale(){
if (ticket > 0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " :ticket = " + ticket--);
}
}
}
3.synchronized 방법 과 synchronized 동기 코드 블록 의 차이 점:synchronized 동기 코드 블록 은 이 코드 블록 만 잠 겨 있 을 뿐 코드 블록 밖의 코드 는 접근 할 수 있 습 니 다.
synchronized 방법 은 굵 은 입자 의 병발 제어 로 어느 순간 하나의 스 레 드 만 이 synchronized 방법 을 실행 할 수 있 습 니 다.
synchronized 동기 화 코드 블록 은 입자 도의 병행 제어 로 블록 중의 코드 만 동기 화 할 수 있 고 코드 블록 이외 의 코드 는 다른 스 레 드 에 의 해 동시에 접근 할 수 있 습 니 다.
보충:다 중 스 레 드 동기 화 잠 금 synchronized(대상 잠 금 및 전체 잠 금)요약
1.synchronized 동기 자물쇠 도입
/*
*
* */
// , " "
class MyRunnable1 implements Runnable{
private int num = 10;
public void run() {
try {
if(num > 0) {
System.out.println(""+Thread.currentThread().getName()+" "+",num= "+num--);
Thread.sleep(1000);
System.out.println(""+Thread.currentThread().getName()+" ");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}public class Test5_5{
public static void main(String[] args) {
MyRunnable1 myRunnable1 = new MyRunnable1();
Thread thread1 = new Thread(myRunnable1," 1");
Thread thread2 = new Thread(myRunnable1," 2");
thread1.start();
thread2.start();
}
}
상기 사례 는 두 스 레 드 가 동기 화 되 지 않 은 방법 을 동시에 방문 하 는 것 을 설명 한다.만약 에 두 스 레 드 가 업무 대상 중의 인 스 턴 스 변 수 를 동시에 조작 하면'스 레 드 가 안전 하지 않다'는 문제 가 발생 할 수 있다.
이 를 통 해 우 리 는 synchronized 키 워드 를 도입 하여 동기 화 문 제 를 실현 합 니 다.
자바 에 서 는 synchronized 키 워드 를 사용 하여 스 레 드 동기 화 를 제어 합 니 다.synchronized 코드 세그먼트 가 여러 스 레 드 에 의 해 동시에 실행 되 지 않도록 제어 합 니 다.synchronized 는 방법 적 으로 도 코드 블록 에 사용 할 수 있 습 니 다.
2.대상 잠 금
(1)synchronized 방법(현재 대상 에 잠 금 추가)
위의 코드 를 수정 하면 run()방법 에 synchronized 키 워드 를 추가 하여 동기 화 방법 으로 바 꿉 니 다.
/*
*
* */
class MyRunnable1 implements Runnable{
private int num = 10;
public void run() {
this.print();
}
public synchronized void print() {
if(this.num > 0) {
System.out.println(""+Thread.currentThread().getName()+" "+",num= "+num--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(""+Thread.currentThread().getName()+" ");
}
}
}public class Test5_5{
public static void main(String[] args) {
MyRunnable1 myRunnable1 = new MyRunnable1();
Thread thread1 = new Thread(myRunnable1," 1");
Thread thread2 = new Thread(myRunnable1," 2");
thread1.start();
thread2.start();
}
}
결론:두 스 레 드 가 같은 대상 의 동기 화 방법 을 동시에 방문 할 때 스 레 드 가 안전 할 것 입 니 다.
(2)synchronized 코드 블록(대상 에 잠 금 추가)
동기 코드 블록 을 사용 하려 면 잠 글 대상 을 설정 해 야 하기 때문에 현재 대상 을 잠 글 수 있 습 니 다:this.
/*
*
* */
class MyRunnable1 implements Runnable{
private int num = 10;
public void run() {
try {
synchronized (this) {
if(num > 0) {
System.out.println(""+Thread.currentThread().getName()+" "+",num= "+num--);
Thread.sleep(1000);
System.out.println(""+Thread.currentThread().getName()+" ");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Test5_5{
public static void main(String[] args) {
MyRunnable1 myRunnable1 = new MyRunnable1();
Thread thread1 = new Thread(myRunnable1," 1");
Thread thread2 = new Thread(myRunnable1," 2");
thread1.start();
thread2.start();
}
}
(3)synchronized 자물쇠 다 중 개체
/*
* synchronized
* */
class Sync{
public synchronized void print() {
System.out.println("print :"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("print "+Thread.currentThread().getName());
}
}
class MyThread extends Thread{
public void run() {
Sync sync = new Sync();
sync.print();
}
}
public class Test5_5{
public static void main(String[] args) {
for(int i = 0; i < 3;i++) {
Thread thread = new MyThread();
thread.start();
}
}
}
상기 사례 에 따 르 면 synchronized 가 여러 대상 을 잠 글 때 동기 화 작업 을 할 수 없다 는 것 을 알 수 있 습 니 다.이 를 통 해 키워드 synchronized 가 얻 은 자 물 쇠 는 모두 대상 자물쇠 이지 코드 나 방법(함수)을 자물쇠 로 삼 는 것 이 아 닙 니 다.synchronized 키 워드 를 가 진 방법 이나 synchronized 코드 블록 을 먼저 실행 하 는 스 레 드 는 이 방법 이나 이 코드 블록 이 가지 고 있 는 자물쇠 가 있 습 니 다.다른 스 레 드 는 대기 상태 만 나타 날 수 있 습 니 다.전 제 는 여러 스 레 드 가 같은 대상 에 접근 하 는 것 입 니 다.
공유 자원 의 읽 기와 쓰기 만 동기 화 되 어야 합 니 다.공유 자원 이 아니라면 동기 화 작업 이 필요 없습니다.
3.전역 잠 금
전역 잠 금 을 실현 하 는 데 는 두 가지 방식 이 있 습 니 다.
(1)synchronized 키 워드 를 static 방법 에 사용 합 니 다.
synchronized 를 static 정적 방법 에 추가 하 는 것 은 Class 류 에 자 물 쇠 를 채 우 는 것 이 고,synchronized 를 비 static 방법 에 추가 하 는 것 은 대상 에 자 물 쇠 를 채 우 는 것 입 니 다.Class 잠 금 은 클래스 의 모든 대상 인 스 턴 스 에 작용 할 수 있 습 니 다.
/*
* synchronized static
* */
class Sync{
static public synchronized void print() {
System.out.println("print :"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("print "+Thread.currentThread().getName());
}
}
class MyThread extends Thread{
public void run() {
Sync.print();
}
}
public class Test5_5{
public static void main(String[] args) {
for(int i = 0; i < 3;i++) {
Thread thread = new MyThread();
thread.start();
}
}
}
(2)클래스 의 클 라 스 대상 을 synchronized 로 잠 금
synchronized(class)코드 블록 의 역할 은 synchronized static 방법의 역할 과 같 습 니 다.
/*
* synchronized Class
* */
class Sync{
public void print() {
synchronized (Sync.class) {
System.out.println("print :"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("print "+Thread.currentThread().getName());
}
}
}
class MyThread extends Thread{
public void run() {
Sync sync = new Sync();
sync.print();
}
}
public class Test5_5{
public static void main(String[] args) {
for(int i = 0; i < 3;i++) {
Thread thread = new MyThread();
thread.start();
}
}
}
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.만약 잘못 이 있 거나 완전히 고려 하지 않 은 부분 이 있다 면 아낌없이 가르침 을 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
javasynchronized 동기화 정적 방법과 동기화 비정적 방법의 공통점우리는synchronized를 사용하여 대상 변수를 동기화할 수 있을 뿐만 아니라,synchronizedl를 통해 동기화 클래스의 정적 방법과 비정적 방법을 동기화할 수 있습니다. 자바 관련 문법에서 알 수 있듯이s...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.