Java中的同步是什么?

  • Post category:Java

当多个线程同时访问共享资源时,可能会引发竞态条件(race condition)。竞态条件指的是多个线程在不正确的时间间隔内访问了共享数据,导致程序产生一些不可预料的结果。为了避免竞态条件,Java提供了同步机制,即保证在同一时间只有一个线程可以访问共享数据,从而保证程序执行结果的正确性。

Java中的同步可以使用synchronized关键字来实现,一个临界区域(也称为同步块)内只能有一个线程访问。synchronized可以用于方法,也可以用于代码块。通过synchronized实现同步时,还需要考虑到以下几点:

1.保证多个线程访问同一个临界区域
2.多个线程需要共享同一把锁
3.被锁住的对象应当是final类型的,为了避免发生指针的变更而导致不安全

下面是一个简单的Java同步示例,使用synchronized来控制多线程并发访问:

public class SynchronizedExample {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized void decrement() {
        count--;
    }

    public synchronized int getCount() {
        return count;
    }
}

在上面的示例代码中,利用synchronized关键字对count变量的三个方法进行了同步控制,以保证多线程并发访问时仅有一个线程可以访问。

下面再来介绍一下Java中的Wait与Notify机制,它们可以协同实现同步。

Wait用于暂停线程的执行,以等待其他线程通知自己继续执行。调用wait方法的线程在释放对象锁后会进入阻塞状态,直到其他线程调用同一对象的notify或notifyAll方法才能被唤醒。

Notify和NotifyAll用于唤醒处于阻塞状态的线程。notify方法只会唤醒正在等待中的一个线程,而notifyAll方法会唤醒所有处于等待中的线程。被唤醒的线程在重新获取对象锁后将调用wait方法之后的代码继续执行。

下面是一个简单的Java Wait与Notify示例:

public class WaitAndNotifyExample {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        System.out.println("Thread 1 waits for lock");
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread 1 got notified");
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("Thread 2 got the lock");
                    lock.notify();
                }
            }
        });

        t1.start();
        Thread.sleep(1000);
        t2.start();
    }
}

在上面的示例代码中,t1线程调用wait方法等待lock对象的解锁,t2线程获取了lock对象的锁之后,调用notify方法唤醒t1线程,t1线程继续执行并输出”Thread 1 got notified”。