Synchronized 使用方式

本文详细解读了synchronized在Java中的两种使用方式:方法锁(this对象锁)和对象锁。通过实例演示了如何确保线程同步,以及对象头中锁机制的工作原理。重点讨论了如何在并发编程中正确应用synchronized以达成预期效果。

Synchronized 使用方式

修饰到方法上

以下的m1\m2方法上加锁相当于,把锁加在this对象上,所以只有m1下城执行完成m2线程才可以继续执行

public class T1 {
    private static synchronized void m1() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
                System.out.println("m1");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    private static synchronized void m2() {
        System.out.println("m2");
    }
    public static void main(String[] args) {
        new Thread(T1::m1, "m1").start();
        new Thread(T1::m2, "m2").start();
    }
}

修饰到对象上

下面的示例是启动两个线程进行对count字段--,一个加锁一个不加锁,最后的结果没有得到预期的效果【按照顺序进行递减】,是因为两个线程在并行执行都可以访问到count字段,所以没得到预期的效果。

public class T2 {
    private static int count = 10;
    private static final Object o = new Object();

    private static void m1() {
        synchronized (o) {
            m3();
        }
    }
    private static void m2() {
        m3();
    }
    private static void m3() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
                count--;
                System.out.println(Thread.currentThread().getName() + " count: " + count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        new Thread(T2::m1, "m1").start();
        new Thread(T2::m2, "m2").start();
    }
}

如果要达到预期的效果两个线程同时对操作方法加锁

public class T2 {
    private static int count = 10;
    private static final Object o = new Object();

    private static void m1() {
        synchronized (o) {
            m3();
        }
    }
    private static void m2() {
        synchronized (o) {
            m3();
        }
    }
    private static void m3() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
                count--;
                System.out.println(Thread.currentThread().getName() + " count: " + count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        new Thread(T2::m1, "m1").start();
        new Thread(T2::m2, "m2").start();
    }
}

其实synchronized还可以修饰T.class,本质上synchronized修饰的就是一个实例

从以上的例子来看,synchronized 修饰的是一个实例,锁在java对象中的体现是在,对象头里jvm中采用两个字节来存储对象头,具体是怎么实现的需要阅读代码和查看java对象的字节码在jvm的存储方式.

Java中,`synchronized`关键字主要用于实现线程间的同步,确保多线程环境下数据的一致性和可见性。以下是` synchronized`关键字的主要使用方式及其适用场景。 ### 实例方法上的 `synchronized` 当一个方法被声明为`synchronized`时,它会锁定当前对象(即`this`)。这意味着同一时间只有一个线程可以访问该对象的任何`synchronized`方法。 ```java public class Counter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } } ``` 在这个例子中,`increment()`和`getCount()`都是`synchronized`方法。如果多个线程尝试同时调用这些方法中的任何一个,那么它们将按顺序执行,而不是并发执行[^2]。 ### 静态方法上的 `synchronized` 对于静态方法,`synchronized`关键字锁定的是类的Class对象,而不是实例对象。因此,它控制着对静态成员变量的访问。 ```java public class StaticCounter { private static int staticCount = 0; public static synchronized void staticIncrement() { staticCount++; } public static synchronized int getStaticCount() { return staticCount; } } ``` 这里,无论创建了多少个`StaticCounter`实例,所有线程访问静态`synchronized`方法时都会受到同一个锁的保护。 ### 代码块上的 `synchronized` 有时可能不需要同步整个方法,而只是需要同步方法中的一部分代码。这时就可以使用`synchronized`代码块来指定具体的锁对象。 ```java public class BlockCounter { private int blockCount = 0; private final Object lock = new Object(); public void blockIncrement() { synchronized (lock) { blockCount++; } } public int getBlockCount() { synchronized (lock) { return blockCount; } } } ``` 这种方式提供了更细粒度的控制,并且允许不同的资源由不同的锁来保护,从而提高程序的性能[^4]。 ### 使用场景 - **共享资源访问**:当多个线程需要读写相同的资源时,比如文件或数据库连接,使用`synchronized`可以防止数据竞争。 - **状态一致性**:保证某些操作的状态一致性,例如银行账户余额更新等业务逻辑。 - **事件监听器**:在注册或注销事件监听器时保持线程安全。 - **延迟初始化**:确保单例模式或其他形式的对象懒加载是线程安全的。 通过合理运用上述几种使用方式开发者可以在多种并发编程场景下有效利用`synchronized`关键字来保障程序的安全性和稳定性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值