⑴ synchronized关键字的作用、原理以及锁优化
synchronized关键字主要作用于java中的线程同步,确保线程安全,通过内部锁机制实现。它可以用于修饰代码块或方法。内部锁在Java中扮演着互斥锁的角色,同一时刻最多只有一个线程能获取锁。内部锁在进入synchronized代码块时自动获取,线程退出或抛出异常时释放。除了确保线程同步,synchronized还保证了线程间的可见性和有序性。
synchronized关键字有三种使用方式:修饰代码块、实例方法或静态方法。修饰代码块时,锁的对象为指定的对象实例。实例方法时,锁的对象为当前实例。静态方法时,锁的对象为类的实例,而非当前实例。错误示例2.1通过将方法修饰为静态方法,可以实现正确的同步,无论指向的实例如何。
synchronized的底层原理是通过Javac编译后的字节码实现。在同步块的前后分别形成monitorenter和monitorexit指令,这两个指令需要一个reference类型的参数来指明要锁定和解锁的对象。执行monitorenter指令时,首先尝试获取对象的锁,如果成功,将锁的计数器增加一。执行monitorexit指令时,将锁计数器减一,当计数器为零时,锁被释放。获取锁失败时,线程被阻塞等待。
synchronized修饰的方法没有monitorenter和monitorexit指令,而是通过ACC_SYNCHRONIZED标识来识别为同步方法。JVM通过这个标识来执行同步调用。
JDK1.6之后,HotSpot虚拟机团队实现了一系列锁优化技术,如适应性自旋锁、锁消除、锁粗化、轻量级锁、偏向锁等,以提高锁的效率。这些优化技术主要针对锁的获取和释放过程进行改进。
偏向锁是通过消除无竞争情况下的同步原语来优化性能。当一个线程获取锁后,锁进入偏向模式,后续请求锁的线程无须进行任何同步操作。连续多次请求相同锁的线程可以享受偏向锁带来的性能提升。一旦有其他线程请求锁,偏向模式失效,锁状态被撤销。使用Java虚拟机参数-XX:+UseBiasedLocking可以开启偏向锁。
轻量级锁通过使用CAS操作来实现加锁和解锁。轻量级锁在锁竞争失败时,如果锁对象的状态为偏向锁状态,会直接将偏向锁升级为轻量级锁,并尝试使用自旋获取锁。轻量级锁在解锁时,会将Displaced Mark Word替换回对象头。如果成功,表示没有竞争发生。如果失败,表示存在竞争,锁会膨胀成重量级锁。
自旋锁和自适应自旋是一种优化手段,当线程获取锁失败时,不会立即挂起线程,而是让线程在处理器上进行几个空循环(自旋)。如果获取到锁,线程进入同步块。自旋锁在JDK1.6及之后默认开启。自适应自旋则是根据前一次在同一个锁上的自旋时间以及锁的拥有者的状态来决定自旋等待的时间,以提高性能。
锁消除是另一种优化技术,虚拟机即时编译器在运行时对代码进行分析,如果判断到一段代码中,在堆上所有数据都不会被其他线程访问到,可以将同步操作消除。逃逸分析是锁消除的主要依据,需要在-server模式下进行。使用-XX:+DoEscapeAnalysis参数开启逃逸分析,-XX:+EliminateLocks参数开启锁消除。
锁粗化是指虚拟机探测到一系列连续操作都对同一个对象反复加锁和解锁时,将加锁同步返回扩展到整个操作序列的外部,只需要加锁一次。这可以减少不必要的性能损耗。
⑵ Java怎么使用synchronized声明一个变量
首先要说明的是,java里不能直接使用synchronized声明一个变量,而是使用synchronized去修饰一个代码块或一个方法。x0dx0ax0dx0a详细说明如下:x0dx0ax0dx0a synchronized用来修饰一个方法或者一个代码块,它用来保证在同一时刻最多只有一个线程执行该段代码。x0dx0a 一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另简圆一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。x0dx0a 二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。x0dx0a 三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访明悉问将被阻塞。x0dx0a 四、第三激咐乎个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。x0dx0a 五、以上规则对其它对象锁同样适用。x0dx0ax0dx0a示例代码:x0dx0apublic class Thread1 implements Runnable { x0dx0a public void run() { x0dx0a synchronized(this) { x0dx0a for (int i = 0; i < 5; i++) { x0dx0a System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); x0dx0a } x0dx0a } x0dx0a } x0dx0a public static void main(String[] args) { x0dx0a Thread1 t1 = new Thread1(); x0dx0a Thread ta = new Thread(t1, "A"); x0dx0a Thread tb = new Thread(t1, "B"); x0dx0a ta.start(); x0dx0a tb.start(); x0dx0a }x0dx0a}x0dx0a结果: x0dx0a A synchronized loop 0 x0dx0a A synchronized loop 1 x0dx0a A synchronized loop 2 x0dx0a A synchronized loop 3 x0dx0a A synchronized loop 4 x0dx0a B synchronized loop 0 x0dx0a B synchronized loop 1 x0dx0a B synchronized loop 2 x0dx0a B synchronized loop 3 x0dx0a B synchronized loop 4
⑶ java中的synchronized()的具体作用
synchronized()
作用是:防止多个线程同一时间调用此代码块或者方法.