synchronized原理及其相关特性

本文详细介绍了Java中的synchronized关键字,包括其用法、同步代码块、静态同步方法,以及synchronized的可重入性和异常处理特性。通过示例解析了synchronized如何保证线程安全,并讨论了其在单例模式中的应用和volatile关键字的作用。
摘要由CSDN通过智能技术生成

写在前面:尽量不要使用 synchronized(String a) 因为在JVM中,字符串常量池具有缓冲功能!而这个会导致线程一直循环,因为String的引用只有一个,会导致只有一个线程不断循环执行。

1.synchronized

synchronized:可以在任意对象及方法上加锁,而加锁的这段代码称为互斥区或临界区。

synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。

采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁。每个对象都有一个monitor(锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池。任何一个对象系统都会为其创建一个互斥锁,这个锁是为了分配给线程的,防止打断原子操作。每个对象的锁只能分配给一个线程,因此叫做互斥锁。

synchronized用的锁是存在Java对象头里。如果对象是数组类型,则虚拟机用3个字宽(Word)存储对象头,如果对象是非数组类型,则用2字宽存储对象头。在32位虚拟机中,1字宽等于4字节,即32bit,如下表所示。

Java对象头里的Mark Word里默认存储对象的HashCode、分代年龄和锁标记位。32位JVM的Mark Word的默认存储结构如表所示。

在运行期间,Mark Word里存储的数据会随着锁标志位的变化而变化。Mark Word可能变化为存储以下4种数据,如表2-4所示。
 

在64位虚拟机下,Mark Word是64bit大小的,其存储结构如表2-5所示。

Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:

  1. 普通同步方法,锁是当前实例对象

  2. 静态同步方法,锁是当前类的class对象

  3. 同步方法块,锁是括号里面的对象

其实synchronized相当于是一个“对象监控器”锁,这个对象监控器由不同的对象充当。

当一个线程访问同步代码块时,它首先是需要得到锁才能执行同步代码,当退出或者抛出异常时必须要释放锁。

public class MyThread extends Thread {
    private int count = 5;
    @Override
    public synchronized void run() {
        count‐‐;
        System.out.println(this.currentThread().getName() + " count:" + count);
} 
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread thread1 = new Thread(myThread, "thread1");
        Thread thread2 = new Thread(myThread, "thread2");
        Thread thread3 = new Thread(myThread, "thread3");
        Thread thread4 = new Thread(myThread, "thread4");
        Thread thread5 = new Thread(myThread, "thread5");
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        thread5.start();
    }
}

输出结果:

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值