java线程二之synchronized

1.      当存在多个线程操作共享数据时,必须要保证在同一时刻有且只有一个线程在操作共享数据,其它线程必须等到该线程处理完后再进行操作。在java中,用关键字synchronized可以做到这一点。

 

2.      Synchronized有三种应用方式

a)        修饰代码块

Synchronized(this){

  doSomething();

}

b)        修饰实例方法

Public synchronized void doSomething(){

}

c)        修饰静态方法

Public static synchronized void doSomething(){

}

其中修饰实例方法和修饰静态方法,他们两者之间不互斥,因为一个是获取实例的锁,一个是获取类对象的锁。

 

3.      Synchronized属于重量级锁,效率很低下,因为synchronized指针指向的是monitor(监视器锁)对象,而monitor是依赖于底层的操作系统Mutex Lock来实现的,而操作系统实现线程之间的切换需要从用户态转换到核心态,这个状态的转换需要比较长的时间,时间成本比较高。而在java6以后从jvm层面对synchronized做了较大的优化。

 

4.      Java6以后的锁的状态总共分为五种:无锁状态,偏向锁,轻量级锁,自旋锁和重量级锁。其中重量级的锁就是synchronized

a)        偏向锁

适用于同一个线程获得锁。如果一个线程获得了锁,那锁就进入偏向模式,当这个线程再次请求锁时,不需要再做锁申请的动作,可以直接获取锁,从而提升性能。

但是如果锁竞争比较激烈,偏向锁就失效了,因为每次申请锁的线程都是不相同的。

当偏向锁失败后,先升级为轻量级锁。

b)        轻量级锁

适用于在整个同步时间内不存在竞争,线程交替执行同步块的场合。

c)        自旋锁

轻量级锁失败后,会进行自旋锁的优化手段。当一个线程获得锁,虚拟机让其它想要获取锁的线程做几个空循环,一般不会太久,可能是50个或100个循环,如果循环后能够得到锁,则继续执行,如果得不到,就只能升级为重量锁了。

d)        锁消除

这是另个一种锁的优化,通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁。

         举例如下:

public void add(String str){
    StringBuffer sb=new StringBuffer("");
    sb.append("aaa");
}

StringBuffer是线程安全的,它的append方法是同步的。

public synchronized StringBuffer append(String str) {
    super.append(str);
    return this;
}

按正常来说,这儿会有线程竞争的,但是StringBuffer这个变量是在方法体中的,方法体中的变量都是线程安全的(关于这个,可以参考我的下一篇关于线程的文章—线程安全与不安全的情况),因此jvm会自动将StringBuffer的锁消除,不进行线程的同步竞争。

 

5.      synchronized的重入特性

当一个线程通过synchronized获取锁的时候,在持有锁期间,再次获取这个锁,是可以直接获取的,这儿不会产生锁的竞争。

public class Test {
    public void add(){
        synchronized(this){
            System.out.println("获取锁");
            synchronized(this){
                System.out.println("再次获取锁");
            }
        }
    }
    public static void main(String[] args){
        final Test t=new Test();
        new Thread(){
            public void run(){
                t.add();
            }
        }.start();
    }
}

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值