线程之同步

线程同步三种方式
重入锁ReentrantLock代码块同步:
Lock mLock = new ReentrantLock();
 mLock.lock();
 try{
     //do something
    } finally{
    mLock.unlock();
    }

    这种同步确保了同一时间只能有一个任务访问的代码区。值得注意的是一定要把解锁的操作放在finally,这样代码区发生异常时锁能释放掉,否则其他线程将永远被阻塞。
    一般来说Lock会配合Condition一起使用。调用Condition.await()方法会阻塞该线程,调用Condition.signalALL()将会重新激活所有等待的线程。

synchronized同步

对于这种同步大家可能比较熟悉,synchronized同步分为方法同步和代码块同步。

方法同步:

public synchronized void method() {
 ...
}

    此同步方法等同于上方Lock的同步代码块结构,不过这种方法更加简洁。

代码块同步:

synchronized(Object) {
  ...
}

    其获得了Object的锁,Object指的是一个对象。同步代码块是非常脆弱的,通常不推荐使用。

volatile关键字同步

    由于内存模型以及并发编程中的三个特性:原子性、可见性和有序性,而volatitle(详解)无法保证操作的原子性。所以,使用volatile必须具备以下两个条件:
    1. 对变量的写操作不会依赖于当前值。
    2. 改变量没有包含在具有其他变量的不变式中。
    这里我们使用两种场景来举例说明

  • 状态标志
volatile boolean shutdownRequested;
...
public void shutdown(){
shutdownRequested = true;
}

public void doWork() {
while(!shutdownRequested) {
...
  }
}
  • 双层检查模式(DCL)
public class Signleton {
  private volatile static Singleton instance = null;
  public static Singleton getInstance() {
    if (instance == null) {
        synchronized)(this) {
            if (instance == null) {
                instance = new Singleton();
             }
         }
     }
     return instance;
   }
 }
小结

与锁相比,volatile变量是一种非常简单但同时又非常脆弱的同步机制,它在某些情况下将提供优于锁的性能和伸缩性,但在通常情况下我们最好还是使用synchronized。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值