>  기사  >  Java  >  동기화란 무엇입니까? 동기화를 사용하는 방법은 무엇입니까?

동기화란 무엇입니까? 동기화를 사용하는 방법은 무엇입니까?

PHP中文网
PHP中文网원래의
2017-06-21 13:27:182301검색

synchronized

머리말

운영 체제를 배울 때 하나의 지식 포인트는 한 번에 하나의 프로세스에서만 작동할 수 있는 리소스입니다. 멀티 스레딩을 사용하면 동시에 작동하며 동시에 하나의 리소스에 대한 액세스 및 수정을 제어할 수 없습니다. 제어하려는 경우 오늘은 첫 번째 방법인 스레드 동기화 블록 또는 스레드 동기화에 대해 이야기하겠습니다. 메서드( 동기화)

  1. 다음은 synchronized 키워드synchronized关键字的使用

线程同步方法

public class Sychor {public void insert(Thread thread) {for (int i = 0; i < 10; i++) {
            System.out.println(thread.getName() + "输出:  " + i);
        }

    }public static void main(String[] args) {final Sychor sychor = new Sychor();

        Thread t1 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        Thread t2 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        t1.start();
        t2.start();
    }
}

其中输出结果为下图

동기화란 무엇입니까? 동기화를 사용하는 방법은 무엇입니까?

从上面的结果可以看出这里的两个线程是同时执行insert()方法的,下面我们在原有的代码上添加synchronized关键字看看效果如何,代码如下:

public class Sychor {public synchronized void insert(Thread thread) {for (int i = 0; i < 10; i++) {
            System.out.println(thread.getName() + "输出:  " + i);
        }

    }public static void main(String[] args) {final Sychor sychor = new Sychor();

        Thread t1 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        Thread t2 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        t1.start();
        t2.start();
    }
}

上面程序的동기화란 무엇입니까? 동기화를 사용하는 방법은 무엇입니까?我就不列出来,自己可以试试,总之就是加上了synchronized关键字使得线程是一个一个的执行的,只有先执行完一个线程才能执行了另外一个线程。

线程同步块

当然上面的我们使用的是线程同步方法,我们可以使用线程同步块,这两个相比线程同步块更加灵活,只需要将需要同步的代码放在同步块中即可,代码如下;

public class Sychor {public void insert(Thread thread) {synchronized (this) {for (int i = 0; i < 10; i++) {
                System.out.println(thread.getName() + "输出:  " + i);
            }
            
        }
        

    }public static void main(String[] args) {final Sychor sychor = new Sychor();

        Thread t1 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        Thread t2 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        t1.start();
        t2.start();
    }
}

从上面的代码中可以看出这种方式更加灵活,只需要将需要同步的代码方法在同步块中,不需要同步的代码放在外面

详细原因

  1. 我们知道每一个对象都有一把锁,当我们使用线程同步方法或者线程同步块的时候实际上获得是对象的唯一的一把锁,当一个线程获得了这唯一的锁,那么其他的线程只能拒之门外了,注意这里我们说是一个对象,也就是说是同一个对象,如果是不同的对象,那么就不起作用了,因为不同对象有不同的对象锁,比如我们将上面的程序改成如下:

public class Sychor {public void insert(Thread thread) {synchronized (this) {for (int i = 0; i < 10; i++) {
                System.out.println(thread.getName() + "输出:  " + i);
            }
        }

    }public static void main(String[] args) {//第一个线程Thread t1 = new Thread() {public void run() {
                Sychor sychor = new Sychor();   //在run() 方法中创建一个对象sychor.insert(Thread.currentThread());
            };
        };//第二个线程Thread t2 = new Thread() {public void run() {
                Sychor sychor = new Sychor();  //创建另外的一个对象sychor.insert(Thread.currentThread());
            };
        };

        t1.start();
        t2.start();
    }
}

从上面的结果可知,此时线程同步块根本不起作用,因为他们调用的是不同对象的insert方法,获得锁是不一样的

  1. 上面我们已经说过一个对象有一把锁,线程同步方法和线程同步块实际获得的是对象的锁,因此线程同步块的括号中填入的是this,我们都知道this在一个类中的含义

  1. 一个类也有唯一的一把锁,我们前面说的是使用对象调用成员方法,现在如果我们要调用类中的静态方法,那么我们可以使用线程同步方法或者同步块获得类中的唯一一把锁,那么对于多个线程同时调用同一个类中的静态方法就可以实现控制了,代码如下:

public class Sychor {// 静态方法public static synchronized void insert(Thread thread)  
    {for(int i=0;i<10;i++)
        {
            System.out.println(thread.getName()+"输出     "+i);
        }
    }public static void main(String[] args) {//第一个线程Thread t1 = new Thread() {public void run() {
                Sychor.insert(Thread.currentThread());  //直接使用类调用静态方法};
        };//第二个线程Thread t2 = new Thread() {public void run() {
                Sychor.insert(Thread.currentThread());   //直接使用类调用静态方法};
        };

        t1.start();
        t2.start();
    }
}

注意

  1. 要想实现线程安全和同步控制,如果执行的是非static同步方法或者其中的同步块,那么一定要使用同一个对象,如果调用的是static同步方法或者其中的同步块那么一定要使用同一个类去调用

  1. 如果一个线程访问的是static同步方法,而另外一个线程访问的是非static的同步方法,此时这两个是不会发生冲突的,因为一个是类的锁,一个是对象的锁

  1. 如果使用线程同步块,那么同步块中的代码是控制访问的,但是外面的代码是所有线程都可以访问的

  1. 当一个正在执行同步代码块的线程出现了异常,那么jvm

스레드 동기화 방법

rrreee

출력 결과는 아래와 같습니다

 Running results

위 결과에서 여기 두 스레드가 insert() 메서드를 동시에 실행하는 것을 볼 수 있습니다. 다음으로 synchronized를 원래 코드에 적용하여 효과를 확인하면 코드는 다음과 같습니다.🎜🎜
rrreee
🎜🎜실행 목록은 표시하지 않겠습니다. 위 프로그램의 결과를 직접 시도해 볼 수 있습니다. 간단히 말해서 synchronized 키워드가 추가되어 스레드가 하나씩 실행됩니다. 한 스레드가 먼저 실행되어야 다른 스레드가 실행될 수 있습니다. 🎜🎜

스레드 동기화 블록

🎜🎜물론 위의 스레드 동기화 방법을 사용했지만 스레드 동기화 블록을 사용할 수 있습니다. 이 두 가지는 스레드 동기화 블록보다 더 유연하며 동기화해야 하는 코드만 동기화 블록에 넣으면 코드는 다음과 같습니다. 🎜🎜
rrreee
🎜🎜위 코드에서 볼 수 있듯이 이 방법이 더 유연합니다. 동기화가 필요한 코드 메서드를 추가합니다. 동기화할 필요가 없는 코드는 외부에 배치됩니다. 🎜🎜

자세한 이유

🎜🎜🎜🎜우리는 각 객체를 알고 있습니다. 스레드 동기화를 사용할 때 잠금이 있습니다. 메서드나 스레드가 블록을 동기화할 때 실제로는 개체에 대한 유일한 잠금을 획득합니다. 스레드가 이 고유한 잠금을 획득하면 다른 스레드만 종료될 수 있습니다. 여기서는 객체라고 하며, 즉 동일한 객체라고 말합니다. 객체가 다르면 객체 잠금이 다르기 때문에 작동하지 않습니다. 예를 들어 위 프로그램을 다음과 같이 변경합니다. 다음: 🎜🎜🎜🎜
rrreee
🎜🎜위 결과를 보면 현재 스레드 동기화 블록이 전혀 작동하지 않는 것을 알 수 있습니다. 왜냐하면 스레드의 insert 메소드를 호출하기 때문입니다. 다른 객체, 그리고 잠금을 얻는 것은 다릅니다🎜🎜 🎜🎜🎜🎜위에서 객체에 잠금이 있다고 말했습니다. 스레드 동기화 방법과 스레드 동기화 블록은 실제로 객체의 잠금을 얻습니다. 스레드 동기화 블록의 괄호는 this로 채워집니다. 우리 모두는 클래스🎜🎜🎜🎜🎜🎜🎜🎜클래스에서 this의 의미를 알고 있습니다. 고유 잠금 앞서 말한 것은 개체를 사용하여 멤버 메서드를 호출하는 것입니다. 이제 클래스에서 정적 메서드를 호출하려면 스레드 동기화 메서드나 동기화 블록을 사용하여 유일한 잠금을 얻을 수 있습니다. 클래스를 잠그면 여러 스레드가 동시에 동일한 클래스의 정적 메서드를 호출하여 달성할 수 있습니다. 제어되는 코드는 다음과 같습니다. 🎜🎜🎜🎜
rrreee
🎜Note🎜🎜🎜🎜🎜실행이 비정적인 경우 스레드 안전성과 동기화 제어를 달성하려면 >동기화된 메서드 또는 동기화된 블록이 정적 동기화 메서드 또는 동기화된 블록인 경우 동일한 개체를 사용해야 합니다. 호출된 경우 동일한 클래스를 사용하여 호출해야 합니다. 한 스레드가 정적 동기화 메서드에 액세스하고 다른 스레드가 비정적 동기화 메서드에 액세스하는 경우 두 스레드는 충돌하지 않습니다. 하나는 클래스 잠금이고 다른 하나는 객체 잠금이기 때문입니다🎜 🎜🎜🎜🎜🎜🎜🎜스레드 동기화 블록을 사용하는 경우 동기화 블록의 코드는 액세스가 제어되지만 외부 코드는 모든 스레드에서 액세스 가능합니다. 🎜🎜🎜🎜🎜🎜🎜🎜동기화된 코드 블록이 실행 중일 때 스레드에서 예외가 발생하면 jvm은 현재 스레드가 차지한 잠금을 자동으로 해제하므로 교착 상태가 발생하지 않습니다. 예외🎜🎜🎜🎜🎜참조 기사🎜🎜🎜🎜🎜🎜

위 내용은 동기화란 무엇입니까? 동기화를 사용하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.