Java synchronized修饰符

引言

在多线程编程中,为了保证共享资源的正确访问,我们需要使用同步机制来控制多个线程的执行顺序和互斥访问。Java提供了synchronized修饰符来实现同步,通过对代码块或方法进行同步,可以确保在同一时间只有一个线程访问被同步的代码。

本文将介绍Java中synchronized修饰符的使用方法,包括使用synchronized修饰代码块和方法,以及synchronized的实现原理。

流程图

st=>start: 开始
op1=>operation: 获取锁
op2=>operation: 执行同步代码
op3=>operation: 释放锁
e=>end: 结束

st->op1->op2->op3->e

使用synchronized修饰代码块

使用synchronized修饰代码块可以实现对指定对象的同步访问。以下是使用synchronized修饰代码块的步骤:

步骤 代码 描述
1 synchronized (obj) { 使用synchronized关键字后面跟着小括号,括号中是要进行同步的对象
2 // 同步代码 在代码块中编写需要同步执行的代码
3 } 代码块结束

下面是一个示例,展示了如何使用synchronized修饰代码块:

class MyClass {
    private Object lock = new Object();

    public void synchronizedMethod() {
        synchronized (lock) { // 步骤1
            // 同步代码,例如对共享资源进行访问
            // ...
        } // 步骤3
    }
}

在上面的示例中,我们创建了一个私有对象lock作为同步锁。在synchronized代码块中,对lock对象进行了同步操作。只有获取到lock对象的线程才能执行代码块中的代码,其他线程将被阻塞,直到获取到lock对象。

使用synchronized修饰方法

除了可以使用synchronized修饰代码块外,还可以使用synchronized修饰方法来实现同步。使用synchronized修饰方法可以确保整个方法在同一时间只有一个线程执行。

使用synchronized修饰方法的步骤如下:

步骤 代码 描述
1 public synchronized void methodName() { 在方法声明中添加synchronized关键字
2 // 同步代码 在方法中编写需要同步执行的代码
3 } 方法结束

下面是一个示例,展示了如何使用synchronized修饰方法:

class MyClass {
    public synchronized void synchronizedMethod() { // 步骤1
        // 同步代码,例如对共享资源进行访问
        // ...
    } // 步骤3
}

在上面的示例中,我们将synchronized关键字添加到了方法声明中,从而实现了对整个方法的同步。只有获取到synchronizedMethod方法的线程才能执行该方法中的代码,其他线程将被阻塞,直到获取到该方法。

synchronized的实现原理

Java中的synchronized关键字的实现是基于对象的监视器锁(monitor),每个对象都有一个与之相关联的监视器锁。

当线程进入一个synchronized代码块或方法时,它将尝试获取对象的监视器锁。如果该锁已被其他线程获取,则线程将被阻塞,直到获取到监视器锁。一旦线程持有了监视器锁,它就可以执行同步代码,直到离开synchronized代码块或方法,然后释放监视器锁。

Java中的每个对象都有一个与之关联的锁标记(lock),用于存储关于锁的信息。锁标记可以是偏向锁、轻量级锁或重量级锁。根据锁的状态,JVM