作为一个Java开发,在有多线程竞争同一个资源的时候,为了达到原子性。首先想到的解决方案就是使用synchronized(同步),这个已经成为了我们在开发过程中百试不爽的良药。
Synchronized
synchronized保证方法或者代码块在运行时,同一时刻只有一个线程获取到锁进入,当执行完成或者抛出异常时线程释放锁。synchronized同时还保证共享变量的内存可见性。
Java提供了两种内置方式来使线程同步的访问数据:同步代码块和同步方法。在实现机制上有所不同:
1,同步代码块:当Java源代码被编译成字节码时,会在同步代码块的入口和退出位置分别插入monitorenter和monitorexit指令;当线程执行到monitorenter的时候要先获得所锁,才能执行后面的方法。当线程执行到monitorexit的时候则要释放锁。
2,同步方法:在编译阶段会被翻译成普通方法,在字节码层面并没有任何特别的指令来实现被synchronized修饰的方法,而是在Class文件的方法表中将该方法的方法表中访问标识(access_flags)字段中的synchronized标志位置为1(ACC_SYNCHRONIZED),表示该方法是同步方法并使用调用该方法的对象或该方法所属Class在JVM的内部对象作为锁对象;
当某个线程要访问某个方法的时候,会检查是否有ACC_SYNCHRONIZED,如果有设置,则需要先获得监视器锁(Monitor):Java并发那些事儿-Moniter - 简书,然后开始执行方法,方式执行之后再释放监视器锁。这时如果其他线程来请求执行方法,会因为无法获得监视器锁而被阻断住。值得注意的是,如果在方法执行过程中,发生了异常,并且方法内部并没有处理该异常,那么在异常被抛到方法外面之前监视器锁会被自动释放。
网友评论