java同步方式

1、voliate 

 

voliate 赋予变量在多线程中的可见性,只能作用于变量,非堵塞。java内存模型(如下图)描述了多线程之间信息交换和同步的方式:每个线程都从主内存load一份数据到自己的工作内存,线程对变量的读写操作都是在工作内存中进行的,然后在save到主内存。

 

如果多线程同时操作主内存同意拷贝变量a,那么就可能导致变量的值乱掉,voliate 保证了voliate 变量值修改后的新值立即同步到主内存,每次使用变量也都从主内存刷新数据,即保证了数据在线程间的可见性以及禁止指令重排序。

2、synchronized

synchronize通过加锁堵塞的方式来实现同步,可以修饰变量,方法以及代码块。https://blog.csdn.net/u013795543/article/details/83716108

 

3、AtomicInteger

AtomicInteger的本质:自旋锁+Unsafe的CAS原子操作,非堵塞同步方式(同步指的是一直等待结果,非堵塞是指可以做其他的事情,并不释放cpu资源。)。

 

网上的一则故事比较生动地讲堵塞与同步

故事:老王烧开水。
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
老王想了想,有好几种等待方式
1.老王用水壶煮水,并且站在那里,不管水开没开,每隔一定时间看看水开了没。-同步阻塞
老王想了想,这种方法不够聪明。
2.老王还是用水壶煮水,不再傻傻的站在那里看水开,跑去寝室上网,但是还是会每隔一段时间过来看看水开了没有,水没有开就走人。-同步非阻塞
老王想了想,现在的方法聪明了些,但是还是不够好。
3.老王这次使用高大上的响水壶来煮水,站在那里,但是不会再每隔一段时间去看水开,而是等水开了,水壶会自动的通知他。-异步阻塞
老王想了想,不会呀,既然水壶可以通知我,那我为什么还要傻傻的站在那里等呢,嗯,得换个方法。
4.老王还是使用响水壶煮水,跑到客厅上网去,等着响水壶自己把水煮熟了以后通知他。-异步非阻塞
老王豁然,这下感觉轻松了很多。

对于互斥锁这样的悲观锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁是乐观锁,它不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。

优点:通过CAS保证了原子性

缺点:消耗CPU性能

 

4、ReentrantLock

重入锁底层实现是AbstractQueuedSynchronizer,简称AQS。synchronized是基于JVM层面实现的,而Lock是基于JDK层面实现的。相比synchronized,ReentrantLock可以进行锁的超时和中断设置。重入性是指如果以获取锁的线程再次去获取锁,那么就会获取锁成功,获取锁成功次数加1,后面释放锁锁的次数必须等于之前成所获取锁的的次数,那么该锁才算完全释放。

 

/**
 * Performs non-fair tryLock.  tryAcquire is implemented in
 * subclasses, but both need nonfair try for trylock method.
 */
final boolean nonfairTryAcquire(int acquires) {  //获取锁
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {  //锁是否被占用
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {  //占用锁的线程是否时当前线程
        int nextc = c + acquires;  //如果是,则获取锁次数+1
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}
protected final boolean tryRelease(int releases) {  //释放锁
    int c = getState() - releases;  //上辈子造的孽,一个个减吧
    if (Thread.currentThread() != getExclusiveOwnerThread())  //占用锁的线程是否时当前线程
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {  
        free = true;  //真正释放了
        setExclusiveOwnerThread(null);   //真正释放了
    }
    setState(c);
    return free;
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值